C# Socket.EndReceive工作流
在上,您可以找到C# Socket.EndReceive工作流,c#,sockets,tcp,C#,Sockets,Tcp,在上,您可以找到ReadCallback(IAsyncResult) 我不清楚的是这个if/else语句。如果我们已经阅读了一些东西,为什么我们又开始阅读呢 我们为什么不这样做呢 static void ReadCallback(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; int read = handler.E
ReadCallback(IAsyncResult)
我不清楚的是这个if/else
语句。如果我们已经阅读了一些东西,为什么我们又开始阅读呢
我们为什么不这样做呢
static void ReadCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int read = handler.EndReceive(ar);
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
if(state.sb.Length > 1)
{
string content = state.sb.ToString();
Console.WriteLine($"Read {content.Length} bytes from socket. \nData: {content}");
}
handler.Close();
}
基本上,因为部分消息是一件事 例如,如果您发送1000个字节,那么第一次接收实际上可能只得到30个字节。然后下一个得到70,下一个得到100,然后是50,然后是150,以此类推,直到所有1000字节都被接收到为止(显然,现代网络的数字会更高)。这就是为什么大多数TCP消息都有某种结束标记,或者它们以其大小作为前缀:这样你就知道它们什么时候完成了
请记住:即使您请求100个字节,EndReceive也会提供最多100个字节。它不一定要等到它拥有了所有的字节。我得到了那个部分,但是
EndReceive
(Socket)怎么知道我再次调用它时他已经收到了多少字节呢?我不确定我是否理解。。。它知道您请求了多少字节以及实际得到了多少字节。但就是这样。单独的请求共享的唯一东西是它们不知道的状态对象。你能重新表述你的问题吗?假设我发送了5个字节。我调用BeginReceive
,它将字节存储到缓冲区中,但只得到第一个、第二个和第三个字节。在回调函数中,我检查它是否读取了某些内容,如果读取了,我再次调用BeginReceive
,因为可能有更多的数据,但是现在BeginReceive
如何知道它需要从字节3开始并继续读取?为什么它不从字节0开始,再读取2-3个字节,然后无限次地执行。相反,它知道它已经读取了3个字节,并从字节3(索引2)开始读取。我是说我明白它的作用,但我想知道怎么做,明白了。每次从EndReceive获取缓冲区时,它都会将其重置。缓冲区被重置,并再次从零开始。因此,您需要在调用之间将数据移出缓冲区,并自行组装。因为你是对的;它不知道。这就是为什么这个例子每次都附加在state.sb后面;因为这是接收到的数据的实际存储库。Microsoft socket教程糟糕透顶。不要从中吸取教训。这段代码是最糟糕的方法。在网上找到一些socket教程,并就什么样的方式看起来最好发展自己的想法。@usr现在就开始做。测试并使用2个控制台应用程序:)我将回答您的悬赏问题。@usr我很高兴,yayy:)
static void ReadCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int read = handler.EndReceive(ar);
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
if(state.sb.Length > 1)
{
string content = state.sb.ToString();
Console.WriteLine($"Read {content.Length} bytes from socket. \nData: {content}");
}
handler.Close();
}