0

ソケットを使用してjpgデータを送信するのにいくつか問題があります。

送信側:

Socket client_s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, 4567);
client_s.Connect(serverEP);
NetworkStream stream = new NetworkStream(client_s);
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);

レシーバー側:

clientSocket = listenSocket.Accept();
NetworkStream s = new NetworkStream(clientSocket); 
Bitmap slice_bmp = new Bitmap(s);
Graphics g = this.CreateGraphics();
g.DrawImage(slice_bmp,0,0);

上記を実行すると、Bitmap slice_bmp = new Bitmap(s);送信者のソケットを閉じるまでブロックされます。送信側のソケットが閉じられた後、画像は正常に描画されます。その操作がブロックされている理由を知りたいですか?

また、Bitmap のコンストラクタの引数として Networkstream のインスタンスを使用するのは正しいですか? (私のコードは継承に基づいています)

4

3 に答える 3

2

まず、 のFlush()方法を使用NetworkStreamして、すべてのデータが送信されたことを確認することをお勧めします。

        Socket client_s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint serverEP = new IPEndPoint(IPAddress.Loopback, 4567);
        client_s.Connect(serverEP);
        NetworkStream stream = new NetworkStream(client_s);
        bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
        stream.Flush(); //flush everything

受信側では、最初にイメージのすべてのバイトをbyte配列に読み込む必要があります。そのバイト配列から、そのストリームからMemoryStreamand を構築できます。Bitmap

        clientSocket = listenSocket.Accept();
        NetworkStream s = new NetworkStream(clientSocket);
        int bytesRead = 0;
        int howMany = 0;
        byte [] byteBuffer = new byte[100000];
        do
        {
            howMany = s.Read(byteBuffer, bytesRead, 10000);
            bytesRead += howMany;
            if(bytesRead>=byteBuffer.Length)
                byteBuffer = ResizeByteArray(byteBuffer);
        }
        while (howMany > 0 && s.DataAvailable);
        MemoryStream ms = new MemoryStream(byteBuffer);
        Bitmap slice_bmp = new Bitmap(ms);
        Graphics g = this.CreateGraphics();
        g.DrawImage(slice_bmp, 0, 0);
        g.Dispose();

イメージがインスタンス化されたバイト配列の容量よりも大きい場合は、サイズを変更する必要があります。このヘルパー メソッドを使用できます。

    private byte[] ResizeByteArray(byte[] arr)
    {
        byte[] newArr = new byte[arr.Length * 2];
        Array.Copy(arr, newArr, arr.Length);
        return newArr;
    }

また、補足として、手動で作成DisposeしたGraphicsオブジェクトを常に呼び出します (この場合のように)。コードを確認しましたが、動作します。

于 2013-03-21T09:34:06.957 に答える
0

シングルスレッドアプリケーション、または少なくともマルチスレッドアプリケーションのUI スレッドで作業しているようです。ブロッキングが表示されるのは、ビットマップ オブジェクトがその構築が完了するのを待っているためです。また、ネットワーク経由でストリームから読み取るには時間がかかるため、ビットマップ オブジェクトが完全に作成されるまで、プログラムは続行されません。

プログラムを続行したい場合は、スレッドを作成し、ストリームから読み取ってビットマップを作成する必要があります。ビットマップの準備ができたら、イベントを発生させて適切に動作させることができます。

それNetworkStreamのサブクラスであるSystem.IO.Streamため、完全に問題ありません!anySystem.IO.Streamを使用して、ストリームを必要とするオブジェクトを作成できます。唯一の結果は、経験したように、イメージを作成するよりも少し時間がかかる場合があることSystem.IO.FileStreamです。

MSDNを見てください。ほとんどのことはよく説明されています。

于 2013-03-21T09:06:51.843 に答える
0

これは、ビットマップ クラスが送信の終了を待機するためです。

最初にバイト データ バッファを個別に受信し、そこからメモリ ストリームを作成してからビットマップを作成します。

于 2013-03-21T09:18:55.827 に答える