[英]Sending jpg using tcp socket
我使用套接字发送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构造函数的参数是否正确? (我的代码基于继承)
首先,我建议你使用NetworkStream
Flush()
方法来确保所有数据都已发送。
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
数组。 从该字节数组中,您可以构造MemoryStream
而不是该流中的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
on Graphics
对象(如本例所示)。 我检查了代码,它的工作原理。
您似乎正在处理单个线程应用程序,或者至少在多线程应用程序的UI线程上。 出现阻塞是因为您的位图对象正在等待其构造完成 。 由于通过网络从流中读取需要一段时间,因此在完全创建位图对象之前,程序将不会继续。
如果您希望程序继续运行,则需要创建一个线程并从流中读取并创建位图。 当位图准备就绪时,您可以触发事件并采取适当的行动。
由于NetworkStream
是System.IO.Stream
的子类,因此非常好! 您可以使用任何System.IO.Stream
来创建需要流的对象。 唯一的结果是,正如您所经历的那样,它可能比创建图像需要更长的时间,例如从System.IO.FileStream
。
看看MSDN的大部分内容都有很好的描述。
这是因为位图类等待传输结束:
首先分别接收字节数据缓冲区,然后从中创建内存流,然后创建位图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.