C# EndReceive从不返回0,您如何知道tcp/ip中的数据包何时完成?

C# EndReceive从不返回0,您如何知道tcp/ip中的数据包何时完成?,c#,asynchronous,tcp,C#,Asynchronous,Tcp,这与我的最后一个问题类似。我正在制作一个简单的tcp/ip聊天程序,我在使用EndReceive回调函数时遇到了一些困难。我粘贴了Microsoft的实现(见下文),我注意到,如果消息已全部读取,则在发送下一条消息之前不会运行回调函数,即EndReceive永远不会返回0。例如,如果我发送一条5个字符的文本消息,缓冲区大小为20,“read”将为5,我将处理该字符串并调用BeginReceive,但是BeginReceive在服务器发送另一条消息之前不会运行。由于s.EndReceive从不返回

这与我的最后一个问题类似。我正在制作一个简单的tcp/ip聊天程序,我在使用EndReceive回调函数时遇到了一些困难。我粘贴了Microsoft的实现(见下文),我注意到,如果消息已全部读取,则在发送下一条消息之前不会运行回调函数,即EndReceive永远不会返回0。例如,如果我发送一条5个字符的文本消息,缓冲区大小为20,“read”将为5,我将处理该字符串并调用BeginReceive,但是BeginReceive在服务器发送另一条消息之前不会运行。由于s.EndReceive从不返回0,因此从未到达else部分。我如何知道何时完全接收到数据

public static void Read_Callback(IAsyncResult ar){
 StateObject so = (StateObject) ar.AsyncState;
 Socket s = so.workSocket;

 int read = s.EndReceive(ar);

 if (read > 0) {
            so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
            s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
                                  new AsyncCallback(Async_Send_Receive.Read_Callback), so);
 }
 else{
      if (so.sb.Length > 1) {
           //All of the data has been read, so displays it to the console
           string strContent;
           strContent = so.sb.ToString();
           Console.WriteLine(String.Format("Read {0} byte from socket" + 
                           "data = {1} ", strContent.Length, strContent));
      }
      s.Close();
 }
}

EndReceive
如果流关闭并且所有数据都已被消耗,则很可能会得到0。但是,对于大多数其他用途,流中没有逻辑中断,甚至
NetworkStream.DataAvailable
只告诉您客户端可用的内容,而不是服务器发送的内容。因此,如果在同一个流上发送多个消息/ ETC,则通常需要用期望的字节数对每个块进行前缀,或者使用一些在内容中间通常不期望的分隔符序列。如果内容可能是任意二进制内容,则前者通常更容易实现(即,很难预测不期望的序列),但后者允许在不提前知道长度的情况下进行流式传输(如果您正在动态计算内容,则很有用,否则您可能需要先缓冲内容以了解长度)(或丢弃数据进行试运行)

还要注意的是,
Read
不能保证返回所有可用的数据-发送
“HELLO”
,让
Read
只返回1(the
H
)是完全合法的。因此,您应该期望将多个
Read
调用合并到一条消息中(同样,使用长度前缀或预期的分隔符序列)

在这种情况下,我会尝试发送
HELLO\0
(其中
\0
是一个零字节)。然后我会通过
Read
消费,直到返回