gpt4 book ai didi

c# - EndReceive 永远不会返回 0,你怎么知道数据包在 tcp/ip 中何时完成?

转载 作者:可可西里 更新时间:2023-11-01 02:47:43 26 4
gpt4 key购买 nike

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

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仅告诉您客户端 可用的内容 - 而不是服务器 发送的内容。因此:如果您在同一个流上发送多条消息/等等,通常需要或者为每个 block 添加预期字节数的前缀,或者使用一些分隔符序列通常不会在内容中间出现这种情况。如果内容可以是任意二进制内容,前者通常更容易(即预测一个不期望的序列很棘手),但后者允许流式传输提前知道长度(有用如果您正在即时计算内容,否则您可能需要首先缓冲内容以了解长度(或进行试运行以丢弃数据)。

另请注意 Read不保证返回所有可用数据 - 发送 "HELLO" 是完全合法的, 并有 Read仅返回 1(H)。因此,您应该期望必须合并多个 Read调用单个消息(再次使用长度前缀或预期的定界符序列)。

在这种情况下,我很想发送 HELLO\0 (其中 \0 是一个零字节)。然后我会通过 Read 消费直到 任一个 它返回 <=0 , 一个\0被发现。在\0在这种情况下,在终止符之前缓冲的任何内容都代表一条消息;分隔符之后的任何内容都应作为下一条消息或消息的一部分进行存储和处理。作为测试用例,假设您得到 Read返回 13,序列为 a\0b\0cde\0f\0\0\0g ,这应该 "a" , "b" , "cde" , "f" , "" , "" , "g" (注意不应处理 g - 它可能是尚未收到的较长序列的一部分 - 缓冲直到获得 \0 )。

关于c# - EndReceive 永远不会返回 0,你怎么知道数据包在 tcp/ip 中何时完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4583750/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com