来自 AsyncState 和 EndAccept() 函数的 .NET 套接字之间的区别

Posted

技术标签:

【中文标题】来自 AsyncState 和 EndAccept() 函数的 .NET 套接字之间的区别【英文标题】:Difference between .NET Sockets from the AsyncState and the EndAccept() function 【发布时间】:2012-08-17 21:17:42 【问题描述】:

在阅读这个Async Sockets example 时,我发现了这段代码:

    // Get the socket that handles the client request.
    Socket listener = (Socket) ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

我很难找到关于这两个套接字之间区别的文档,我还想知道关闭处理程序或关闭处理程序将如何影响原始套接字。谁能解释一下,或者给我一些文档?

【问题讨论】:

【参考方案1】:

套接字是特定机器上的唯一连接,即127.0.0.1:1024。一次只能建立一个活动连接。 “侦听器”侦听固定端口(例如我上面示例中的 1024)。它的工作是成为接受连接的“公共”方式。一旦它接受一个连接,它就会在一个新的、随机的(嗯,相当伪随机的)选择端口上创建一个新的套接字。然后原始连接应用程序和主机可以通过该套接字进行通信,从而释放侦听套接字以获取另一个连接(这将为新连接分配另一个端口号,等等)。

EndAccept 通常是您建立连接后需要做的所有事情。 listener 通常会继续侦听以接受更多连接。如果没有,您通常只需处置或关闭套接字以停止侦听并取消任何待处理的接受。 handler 用于执行应用程序需要的任何通信,完全独立于listener 套接字。当您使用完 handler 套接字后,您将处理或关闭它,因为 listener 是独立的,它会继续“运行”。

Shutdown 将刷新面向连接的套接字(在Close 之前调用)上的所有待处理数据,并且不会影响任何其他套接字。

【讨论】:

【参考方案2】:

监听器是监听连接的套接字。您不想让侦听器被占用,否则多个客户端将无法通过该套接字进行连接。在该套接字上调用 EndAccept 会为您提供一个套接字供服务器与客户端通信,并打开侦听器以进行更多连接。

关闭处理程序不应影响侦听器套接字。

【讨论】:

感谢您的信息。在处理程序上调用 ShutDown() 怎么样?有什么见解吗?也许我根本不需要调用它——这很好,Socket 接口是一个大杂烩,只有在某些使用上下文中才有意义。所以,我的想法是我不需要关闭处理程序。 您可能应该在完成处理程序套接字后关闭它,或者该端口将保持打开状态直到您的进程退出。关闭处理程序套接字不会影响侦听器套接字,因此您仍然可以获得传入连接。您的套接字是否存在特定问题?【参考方案3】:

任何基于套接字的 .NET 服务器应用程序都将涉及至少两种套接字:

    用于侦听入站连接(同步或异步)的侦听器套接字 通过调用侦听器套接字的 Accept() 方法返回的客户端套接字。

你说的例子是异步监听,socket首先调用BeginAccept()方法,参数是异步方法的地址。现在,如果您不调用相应的 EndAccept() 方法,则原始侦听器套接字将被阻塞,并且来自客户端的任何进一步连接都可能丢失。

Socket.ShutDown(Both) 方法用于优雅地关闭带有连接的套接字,而 Socket.Disconnect(True) 将强制执行相同的操作。无论如何, Socket.Close() 应该遵循这些方法。有关更多信息,请参阅此 SO 链接:c#/.Net Socket.Shutdown

【讨论】:

以上是关于来自 AsyncState 和 EndAccept() 函数的 .NET 套接字之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

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

csharp Task.AsyncStateの动作を确认する

C#学习笔记13

中止请求 wp7

Thread(线程)三

.NET异步委托