在 EndAccept() 之前或之后开始接受新连接

Posted

技术标签:

【中文标题】在 EndAccept() 之前或之后开始接受新连接【英文标题】:Start Accepting new connections before or after EndAccept() 【发布时间】:2014-06-22 21:57:13 【问题描述】:

我有一个问题,在套接字上的 BeginAccept 之后的什么时候我可以告诉我的侦听器线程它可以再次开始接受连接。

这是我的代码:

while(!mStopWaitHandle.WaitOne(0, false)) // <-- Manual Reset event to check if the service has stopped.

    Logging.Debug("Waiting for a connection...");

    socket.BeginAccept(new AsyncCallback(AcceptConnection), socket);

    mReadyToAcceptWaitHandle.WaitOne(); // <-- AutoResetEvent to block until I can continue accepting connections

然后在我的异步回调中:

private void AcceptConnection(IAsyncResult ar)

    mReadyToAcceptWaitHandle.Set(); // <-- Tell the listener thread to start accepting connections again

    Socket socket = (Socket)ar.AsyncState;
    Socket workerSocket = socket.EndAccept(ar);

    ... handle connection on workerSocket ...

这就是他们在Asynchronous Server Socket Example on msdn 中的做法。

但是从我读到的BeginAccept 不是阻塞调用。阻塞调用是EndAccept,它会阻塞直到有连接可以接受。

所以在 EndAccept() 之前让mReadyToAcceptWaitHandle.Set(); 告诉侦听器线程继续接受连接对我来说似乎很奇怪,因为这不会导致它继续打开AcceptConnection 处理程序线程(从我的从执行上看,它似乎没有这样做,但我不知道为什么?)这一切都只是阻止EndAccept

EndAccept 之后有mReadyToAcceptWaitHandle.Set(); 不是更好吗,这样它一次只处理接受一个连接,一旦它接受,但在它实际处理连接上的通信之前。

这两种方法似乎都有效,但我想知道哪一种是正确的方法,以及一种方法是否会产生另一种没有的微妙负面影响。

我在这里错过了什么?

提前致谢。

【问题讨论】:

【参考方案1】:

The blocking call is EndAccept, and it blocks until there is a connection to accept.

这不是一个准确的描述。

EndAccept 在收到来自客户端的连接请求时从BeginAccept 的回调中调用。您可以从BeginAccept 回调中再次调用BeginAccept 以立即接受另一个连接,同时建立您刚刚通过EndAccept 收到的(上一个)连接(仍在连接回调中)。

因此实际上根本不需要使用事件来同步何时接受新连接。只需从回调中再次调用BeginAccept

【讨论】:

根据 EndAccept 文档msdn.microsoft.com/en-us/library/chfa7866(v=vs.110).aspx 的备注部分,EndAccept 实际上会阻塞,直到传入连接队列中有一个连接可以接受。无论如何,从 BeginAccept 回调中调用 BeginAccept 与在等待 WaitHandle 上的信号后从与原始 BeginAccept 相同的位置调用它没有什么不同,就像我在代码中所做的那样。事实上,我的方式更清洁,并允许我对其他状态进行更多检查,如服务停止。事实上,我的方式是他们在 MSDN 示例中的做法。 你甚至没有回答我的问题。 当它阻塞时,它只会暂时阻塞,因为回调只会在实际上有连接接受时才被调用。 你自己在***.com/a/15557881/2709382的cmets中说BeginAccept不会阻塞。 OHHH AsyncCallback 仅在有要接受的连接时执行,但 BeginAccept 不会阻塞。

以上是关于在 EndAccept() 之前或之后开始接受新连接的主要内容,如果未能解决你的问题,请参考以下文章

在开始睡眠(或直到脚本结束)之后对象输出的奇怪延迟

直到 socket.Close 才收到 Windows socket.Send 数据

git“在X commits之前或之后”是什么意思?

在神经网络开始在训练数据上表现可接受之前的隐藏层数、隐藏层中的单元数和历元数

AH00136:服务器必须在接受连接之前放弃启动权限。请确保已加载 mod_unixd 或其他系统安全模块

之后:日期不接受 Laravel 表单验证中的相同日期?