【问题标题】:When a TCP socket's BeginRecieve fires onDataReceived delegate, what happens with subsequent packets received before BeginReceive is called again?当 TCP 套接字 BeginReceive 触发 onDataReceived 委托时,在再次调用 BeginReceive 之前收到的后续数据包会发生什么情况?
【发布时间】:2011-07-08 16:12:30
【问题描述】:

换句话说,在委托执行开始之间收到的新数据包会发生什么:

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

然后下一次调用该套接字上的 beginReceive?

            s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
                                 new AsyncCallback(Async_Send_Receive.Read_Callback), so);
}

是并行执行第二个 onDataReceived,还是数据在缓冲区中排队,下一个 beginReceive 在被调用后立即触发委托?

【问题讨论】:

    标签: .net sockets


    【解决方案1】:

    数据排队到缓冲区。这些回调在线程池上执行,所以只要调用BeginReceive,就可能会触发回调。

    【讨论】:

    • 但一次只能有一个,对吗? IE它不会并行执行2个回调?因为它在“线程池”中,所以让我想知道“也许每个数据包会产生一个线程”等等。
    • 不,如果一个BeginReceive回调立即再次调用BeginReceive,它可以并行调用两个回调。通常,BeginReceive 回调会将数据传递给另一个线程或队列或其他东西,然后在返回之前调用BeginReceive,所以这不是问题。
    • 是的,我就是这样做的——将数据写入缓冲区,然后在最后调用 BR。如果该缓冲区被锁定了很短的时间,阻塞了回调......那么呢?它仍然应该尽快阻止和写入,对吗?我偶尔有一个 TCP 流被乱序写入我的缓冲区,即使流本身(用wireshark 捕获的数据包)按顺序到达(即使它们乱序,TCP 也可以处理乱序接收它们) ...
    • 如果回调被阻塞,则无法调用BeginReceive,因此无法启动另一个回调。
    • 好吧,这不是我的错,所以我不能负责! :)
    【解决方案2】:

    您必须显式调用 BeginReceive,但在回调完成之前您不应该这样做。请参阅:http://msdn.microsoft.com/en-us/library/bew39x2a.aspx#Y53 以获取适当的示例。 至于更一般的 tcp 问题,我想它取决于 tcp 堆栈实现,但肯定有一个缓冲区,数据在较低级别累积。根据发送方的设置,如果接收方没有人在套接字上调用正确的接收方法,它可能会在缓冲区已满时阻塞。希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-04
      相关资源
      最近更新 更多