使用NetworkStream通知图像流结束

时间:2019-03-04 03:26:50

标签: c#

我有一个客户端-服务器方案,其中客户端每秒将图像发送到服务器。我不想每次发送图像来表示流结束时都关闭连接。我想保持网络流开放,以减少重新建立连接的开销。如何发出图像流结束的信号?

在发送图像字节后,我尝试使用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);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

更新

首先,您需要确定打开和关闭连接的开销是否真的那么糟糕,我的直觉是最小的……如果您完全无法接受,那么您实际上只有2个可靠的选项。发送某种表示结束的字节组合。或在每个图像之前发送一个尺寸,以便您知道尺寸和结束位置。

原始

Read(Byte[], Int32, Int32)

  

注释:此方法将数据读入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.
     }
}