正确停止监听Socket的方法

23

我有一个服务器在一个套接字上监听连接:

public class Server
{
    private Socket _serverSocket;

    public Server()
    {
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 1234));
        _serverSocket.Listen(1);
    }

    public void Start()
    {
        _serverSocket.BeginAccept(HandleAsyncConnectionMethod, null);
    }

    public void Stop()
    {
        //????? MAGIC ?????
    }

    //... rest of code here
}

关闭socket的正确(清晰)方法是什么?

是否只需要调用以下内容:

_serverSocket.Disconnect(true);

在Stop()方法中关闭了连接吗?还是需要进行其他工作来清除连接?

7个回答

4

7
执行 accept(即等待新连接)的套接字现在与连接到客户端的套接字相同(其中“断开”或“关闭”是正确答案之一)。 - Richard
5
@Richard:既然你似乎了解哪些情况需要采取某些行动,也许你可以分享一个答案,而不仅仅是对其他人的回答进行反对。尽管这是一个较旧的帖子,但我相信社区会很感激,因为这个问题有相当多的浏览量(我就是其中之一)。 - Ocelot20
@Ocelot20 1. 请看我的评论(我已经包含了信息)。2. 这不是这个问题的唯一答案。 - Richard

3

因为您正在监听传入的TCP连接,所以可以使用System.Net.Sockets.TcpListener,它具有Stop()方法。但是,它没有异步操作。


通过 Telerik 的反编译器查看内部情况,TcpListener.Stop 只是关闭了底层的监听套接字。它与一个未完成的异步接受操作的交互效果不清楚(但似乎可以工作)。 - Richard

3

两种正确关闭它的方法,避免异常

1) 创建临时连接套接字并将其连接到监听套接字,以便它可以触发其处理程序,然后使用正常的EndAccept完成它,之后关闭两个套接字。

2) 只需Close(0)监听套接字,这将导致对其回调的虚假射击,如果您查看您的监听套接字,您将看到它的状态为“已关闭”和“已处理”。这就是为什么调用EndAccept会导致异常。您可以忽略它并不调用EndAccept。监听套接字将立即关闭而无需超时。


1
我添加了一个名为isShuttingDown的volatile bool变量,初始值为false。当套接字终止时,我将其设置为true。然后在Accept回调函数中,我检查该值,如果为true,则不调用EndAccept。这样做非常好,没有任何异常。 - NickV

0
最干净的让 Accept 调用立即中断的方法是调用 _serverSocket.Dispose(); 其他类似 Shutdown 或 Disconnect 的方法调用都会抛出异常。

-1
首先,您需要确保在BeginAccept过程中创建的任何客户端套接字都被跟踪并关闭。使用Socket.Shutdown()和Socket.Close()方法首先关闭它们。一旦这些都已关闭,然后再对监听套接字本身执行相同的操作。

2
-1:当监听(接受)套接字关闭时,无需停止已连接的套接字。一台仅处理一个客户端的服务器可以在一个客户端连接时合理地关闭接受套接字,然后为新客户端创建一个新的监听套接字。 - Richard

-2

等等,你是在像CodingHorror的帖子一样搞笑呢,还是真的认为尽可能关闭它并将其设置为null是个好主意? - Wim Coenen

-3

2
-1:执行accept(即等待新连接)的套接字现在与连接到客户端的套接字相同(其中一个“断开连接”或“关闭连接”是正确答案)。 - Richard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接