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

  • 服务器等待客户端
  • 客户端连接
  • 服务器等待客户端请求一些内容
  • 客户端最终请求一些内容(例如“请以PDF格式发送Hans Passant的简历吗?”)
  • 服务器适当地回复
  • 服务器等待客户端请求某些内容(即再次返回到第3步)

    该循环一直持续到关闭连接为止。

    引用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并返回)

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

    最佳答案

    TCP连接是面向流的。没有消息的概念。因此,很有可能(至少在不良网络上),您的Write()之一将与多个Read()一起接收,或者多个Write()将与一个Read()一起被接收。您绝对不应依靠Read()在消息/请求中中断流。

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

    您应该看一下BinaryReaderBinaryWriter,这些类可能会使您更简单:ReadString()将读取完整的字符串,而ReadBytes()将读取指定的字节数。

    编辑:为了澄清一点,不保证以64作为大小参数的Socket.Receive()NetworkStream.Read()返回64字节。它们可以返回1、10、32、63或其他值(不是0,除非有超时,否则它将一直阻塞)。另一方面,BinaryReader.ReadBytes(64)保证等待64个字节。连接问题将单独处理,但有异常(exception)。

  • 10-07 13:09
    查看更多