1

Python Imaging Library を使用して画像を描画するサーバー側関数があります。Java クライアントはイメージを要求します。イメージはソケットを介して返され、BufferedImage に変換されます。

送信する画像のサイズをデータの前に付け、その後に CR を付けます。次に、ソケット入力ストリームからこのバイト数を読み取り、ImageIO を使用して BufferedImage に変換しようとします。

クライアントの短縮コード:

public String writeAndReadSocket(String request) {
    // Write text to the socket
    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    bufferedWriter.write(request);
    bufferedWriter.flush();

    // Read text from the socket
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    // Read the prefixed size
    int size = Integer.parseInt(bufferedReader.readLine());

    // Get that many bytes from the stream
    char[] buf = new char[size];
    bufferedReader.read(buf, 0, size);
    return new String(buf);
}

public BufferedImage stringToBufferedImage(String imageBytes) {
    return ImageIO.read(new ByteArrayInputStream(s.getBytes()));
}

そしてサーバー:

# Twisted server code here

# The analog of the following method is called with the proper client
# request and the result is written to the socket.
def worker_thread():
    img = draw_function()
    buf = StringIO.StringIO()
    img.save(buf, format="PNG")
    img_string = buf.getvalue()
    return "%i\r%s" % (sys.getsizeof(img_string), img_string)

これは文字列の送受信には機能しますが、画像変換は (通常) 失敗します。画像が正しく読み取られない理由を理解しようとしています。私の最善の推測は、クライアントが適切なバイト数を読み取っていないということですが、正直なところ、なぜそうなるのかはわかりません。

補足:

  • char[]-to-String-to-bytes-to-BufferedImage Java ロジックは回り道ですが、バイトストリームを直接読み取ると同じエラーが発生します。
  • クライアントソケットが永続的ではない、つまり. 要求が処理され、接続が切断されます。画像サイズを気にする必要がないため、そのバージョンは問題なく動作しますが、提案されたアプローチが機能しない理由を知りたいです。
4

3 に答える 3

2
  1. BufferedReader.read()バッファがいっぱいになる保証はなく、画像を文字列に変換して元に戻すことは無意味であるだけでなく、間違っています。

  2. 文字列はバイナリ データのコンテナーではなく、ラウンドトリップが機能する保証はありません。

を取り除きreadLine()、長さをバイナリで送信し、ストリーム全体をDataInputStream.

一般に、バイナリ プロトコルを扱う場合、バイト オーダーが正規のネットワーク バイト オーダーでない限り、答えは常にDataInputStreamandです。これはプロトコル設計の間違いであり、その場合は byte-ordered を調べる必要があります。DataOutputStreamByteBuffers

于 2012-06-12T22:16:29.130 に答える
1

サーバーコードでは、の使用sys.getsizeofが間違っています。それはバイト文字列オブジェクトのサイズを返しますが、必要なのはバイト文字列のバイト数、つまりその長さlen(img_string)です。

また、クライアント コードでは、メソッドは、またはのいずれかが続く可能性がある.readLineことを確認するまで文字を読み取ります。そのため、画像データの最初のバイトが 0x0A、つまり.'\r''\n''\n''\r''\n'

于 2012-06-12T22:20:01.980 に答える
0

問題は、バイナリ データ (イメージ) を読み取ろ うとしていることにあると思いますReadergetBytes()

スタックはReader、基になるソケット ストリームからバイトを取得し、(プラットフォームの既定の文字エンコーディングを使用して) 文字に変換し、文字列として返します。次に、デフォルトのエンコーディングを再度使用して、文字列の内容をバイトに戻します。バイトから文字への最初の変換は、バイナリ データの場合、「ロッシー」になる可能性があります。

修正はReader/を使用しないことBufferedReaderです。とを使用しInputStreamますBufferedInputStream。画像サイズをテキストとしてエンコードして送信することは簡単ではありませんが、改行を取得するまで一度に 1 バイトずつ読み取り、それらを「手動で」整数に変換することで対処できます。

(サイズが「ネットワーク順序」で固定サイズのバイナリ整数として送信された場合は、DataInputStream代わりに使用できます...)

于 2012-06-12T22:29:58.590 に答える