【问题标题】:Signal end of image stream using NetworkStream使用 NetworkStream 的图像流的信号结束
【发布时间】:2019-03-04 11:47:17
【问题描述】:

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

我尝试在发送图像字节后使用NetworkStream.Flush(),然后发送一个ASCII编码的字符串来表示图像的结束,但是,根据微软的文档,NetworkStream.Flush() 方法无效“因为 NetworkStream 没有缓冲,它对网络流没有影响”。

我该如何解决这个问题?

客户:

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);
        }
    }
}

【问题讨论】:

    标签: c#


    【解决方案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.
         }
    }
    

    【讨论】:

      【解决方案2】:

      更新

      首先,你需要弄清楚打开和关闭连接的开销是否真的那么糟糕,我的直觉是这将是最小的......如果你完全不能接受,那么你真的只有 2 个可靠的选项。发送某种表示结束的字节组合。或者在每张图片之前发送一个尺寸,这样你就知道尺寸和结尾了。

      原创

      Read(Byte[], Int32, Int32)

      备注 该方法将数据读入缓冲区参数并返回 成功读取的字节数。 如果套接字关闭,则 读取方法返回 0。读取操作读取尽可能多的数据 可用,最多为 size 参数指定的字节数。 如果远程主机关闭连接,所有可用数据 已收到,Read 方法立即完成并返回 零字节

      你需要做的就是关闭客户端

      ...
      
      if(SomeCondition)
         break; 
      

      不过,您可能还想在服务器上捕获适当的异常,它们可以并且将会发生

      【讨论】:

      • 关闭连接是我试图避免的。我不希望每秒重新建立连接的开销。
      • @mr.coffee 你的问题对我来说有点不清楚,更新了
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-10
      • 2011-09-15
      • 2017-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多