我有一个客户端-服务器方案,其中客户端每秒将图像发送到服务器。我不想每次发送图像来表示流结束时都关闭连接。我想保持网络流开放,以减少重新建立连接的开销。如何发出图像流结束的信号?
在发送图像字节后,我尝试使用NetworkStream.Flush()
,然后发送ASCII编码的字符串来表示图像结束,但是,根据Microsoft的文档,NetworkStream.Flush()
方法无效,因为“ NetworkStream is没有缓冲,对网络流没有影响。”
我该如何解决这个问题?
客户:
client.Connect(_host, _port);
Console.WriteLine("Connected");
using (NetworkStream stream = client.GetStream())
{
while (_isRunning && client.Connected)
{
byte[] buffer = CaptureScreen();
Console.WriteLine("Sending {0} bytes", buffer.Length);
stream.Write(buffer, 0, buffer.Length);
Thread.Sleep(1000);
}
}
服务器:
using (NetworkStream stream = client.GetStream())
{
while (_isRunning && client.Connected)
{
byte[] buffer = new byte[16384];
using (MemoryStream memoryStream = new MemoryStream())
{
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
_form.ConsoleWriteLine($"Received {bytesRead} bytes");
// TODO: If end of image stream break from read loop
memoryStream.Write(buffer, 0, bytesRead);
}
Image image = Image.FromStream(memoryStream);
_form.UpdateImage(image);
}
}
}
答案 0 :(得分:1)
更新
首先,您需要确定打开和关闭连接的开销是否真的那么糟糕,我的直觉是最小的……如果您完全无法接受,那么您实际上只有2个可靠的选项。发送某种表示结束的字节组合。或在每个图像之前发送一个尺寸,以便您知道尺寸和结束位置。
原始
注释:此方法将数据读入buffer参数并返回 成功读取的字节数。 如果插座关闭,则 读取方法返回0 。读取操作将读取尽可能多的数据 可用,最大为size参数指定的字节数。 如果远程主机关闭连接,则所有可用数据 已收到,Read方法立即完成并返回 零字节。
您需要做的就是关闭客户端
...
if(SomeCondition)
break;
尽管,您可能还想在服务器上捕获适当的异常,但它们可能并且会发生
答案 1 :(得分:1)
您可以在发送图像内容之前发送图像尺寸。
stream.Write(BitConverter.GetBytes(buffer.Length), 0, 4);
stream.Write(buffer, 0, buffer.Length);
在服务器端收到确认字节后立即停止。
int read = stream.Read(buffer, 0, 4);
int imageSize = BitConverter.ToInt32(buffer, 0);
int bytesRead, totalBytesRead = 0;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
totalBytesRead += bytesRead;
if(totalBytesRead == imageSize)
{
//Save image
}
else if(totalBytesRead > imageSize)
{
//May happens, split the buffer.
}
}