Socket.EndReceive工作流程

时间:2019-01-13 13:18:26

标签: c# sockets tcp

microsoft site上,您可以找到ReadCallback(IAsyncResult)的这段代码

static void ReadCallback(IAsyncResult ar)
{
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    int read = handler.EndReceive(ar);

    if(read > 0)
    {
        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
    }
    else
    {
        if(state.sb.Length > 1)
        {
            string content = state.sb.ToString();

            Console.WriteLine($"Read {content.Length} bytes from socket. \nData: {content}");
        }
        handler.Close();
    }
}

我不清楚这个if/else声明。如果我们已经阅读过一些内容,为什么还要再次BeginReceive

我们为什么不做

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();
}

1 个答案:

答案 0 :(得分:1)

基本上,因为部分消息是一回事。

例如,如果您发送了1000个字节,那么第一次接收实际上只能得到30个字节。然后,下一个接收到70个,下一个接收到100个,然后是50个,然后是150个,依此类推,直到接收到所有1000个字节(显然如果使用现代网络,该数字会更高)。这就是为什么大多数TCP消息都带有某种结束标记或它们带有大小前缀的原因:所以您知道它们何时完成。

请记住:即使您请求100个字节,EndReceive也会给您最多 个字节。它不一定要等到全部都拥有。