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);会被阻塞,直到关闭发件人的套接字。发送方的套接字关闭后,正常绘制图像。我想知道为什么该操作被阻止?

另外,使用 Networkstream 的实例作为 Bitmap 的构造函数的参数是否正确?(我的代码是基于继承的)

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 than 。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;
    }

作为旁注,请始终调用您手动创建DisposeGraphics对象(如本例所示)。我检查了代码,它可以工作。

于 2013-03-21T09:34:06.957 回答
0

这是因为位图类等待传输结束:

首先单独接收字节数据缓冲区,然后从中创建内存流,然后创建位图。

于 2013-03-21T09:18:55.827 回答
0

看来您正在处理单线程应用程序,或者至少在多线程应用程序的UI 线程上工作。出现阻塞是因为您的位图对象正在等待其构造完成。并且由于通过网络从流中读取需要一段时间,因此在您的位图对象完全创建之前,您的程序将不会继续。

如果您希望程序继续运行,则需要创建一个线程并从流中读取它并创建位图。当位图准备好时,您可以触发一个事件并采取适当的行动。

作为NetworkStream它的一个子类System.IO.Stream是完全没问题的!您可以使用 anySystem.IO.Stream创建需要流的对象。唯一的结果是,正如您所经历的那样,它可能比创建图像需要更长的时间,例如从System.IO.FileStream.

看看MSDN大部分的东西都有很好的描述。

于 2013-03-21T09:06:51.843 回答