是否有可能稍微延迟接收数据(使用任何.NET tcp套接字协议)

时间:2014-12-30 16:11:26

标签: c# .net sockets tcp

我的客户端 - 服务器应用程序使用此MSDN article提供的基本实现。但是,变化是我没有使用<EOF>类型的分隔符,因为我的应用程序的工作方式是:

  1. 服务器等待客户端
  2. 客户端连接
  3. 服务器等待客户端请求
  4. 客户最终要求提供的东西(例如“请以PDF格式发送Hans Passant的简历?”)
  5. 服务器正确回复
  6. 服务器等待客户端请求某些内容(即再次返回步骤3)
  7. 此循环一直持续到连接关闭为止。

    参考this SO question,是否可以通过从套接字接收数据的任何.NET实现(Socket.Receive,TCP.GetStream()。Read(...)...等。)读取或接收操作是否有可能返回错误的0? (例如,一些数据已被读取,下一个数据包暂时停留在流量中,而读取/接收操作不知道,所以它只是假设没有其他内容可读,只返回零)。

    我的代码如下:

    public void recieveClientData()
            {
                byte[] bs = new byte[1];// 'commStream' is NetworkStream of the socket    
                commStream.Read(bs, 0, 1);//blocks until something comes in 
                // Buffer for reading data 
                Byte[] bytes = new Byte[1024];
                using (MemoryStream m = new MemoryStream())
                {
                    //scoop what we have yet
                    m.Write(bs, 0, 1);
    
                    //get the remaining
                    int length;
    
                    while ((length = commStream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        m.Write(bytes, 0, length);
                    }
    
                    //At this point, 'm' is sent for asyncronously processing
                    ...
    
                    //wait for another data from this client
                    recieveClientData();
                }  
            }
    

    现在在while ((length = commStream.Read(bytes, 0, bytes.Length)) != 0)行,让我们假设客户端正在向服务器发送大约32Mb的PDF文件(因此服务器可以保存它)为了将来检索),当行commStream.Read(bytes, 0, bytes.Length)在循环中执行时,网络延迟可能会阻止该流读取某些内容,这样它就会返回0(意味着有一个网络数据包上的某种网络延迟但在该数据包最终通过并传输之前,commStream.Read已经读取0并返回)

    请注意,我不能在这里使用分隔符,因为传输的数据并不总是字符串。

1 个答案:

答案 0 :(得分:3)

TCP连接是面向流的。没有消息的概念。因此很可能(至少在糟糕的网络上),您的Write()将会收到多个Read(),或者会收到多个Write() Read() Read() 1}}。您永远不应该依赖BinaryReader来打破消息/请求中的流。

通常的方法是提前知道您将收到什么,或者在未知大小的实际数据之前发送大小。使用TCP,可以保证数据不会被破坏,因此您应该依赖它。当然,总是会出现一个大问题并重置连接,但是你会遇到异常,并单独处理它。

您应该查看BinaryWriterReadString(),这些类可能会让您更简单:ReadBytes()将读取字符串完整,Socket.Receive()将准确读取指定的字节数。

编辑:为了澄清一点,NetworkStream.Read()BinaryReader.ReadBytes(64)以64作为 size 参数不保证以64字节返回。它们可以返回1,10,32,63或其他任何东西(不是0,它会保持阻塞,除非有超时)。另一方面,{{1}}保证等待64个字节。连接问题单独处理,但有例外。