如何礼貌地停止 TcpListener?

3

我有一个TCP服务器,它运行良好,但现在我需要以安全的方式停止它和所有线程。

据我所知,中止(Abort)方法不可取。我进行了调试,并且当服务器启动并且没有连接时,代码似乎在该行上停止:

Server = New TcpListener(IPAddress.Any, Port)

当我调用 StopServer 时,会出现有关 WSACancelBlockingCall 的错误,我无法正确地停止服务器。
以下是完整的代码,除了接收数据的 StartTcpClient。
#Region "TCP Receive variables"
    Dim TcpOpen As Boolean = False
    Private Server As TcpListener = Nothing
    Private ServerThread As Thread = Nothing
    Friend AckString As String = ""
#End Region

#Region "TCP"
    Public Sub StopServer()
        Server.Stop()
        ServerThread.Abort()
        TcpOpen = False
    End Sub
    Public Sub InitServer(ByVal Port As Integer)
        Server = New TcpListener(IPAddress.Any, Port)
        ServerThread = New Thread(AddressOf ConnectionListener)
        ServerThread.IsBackground = True
        ServerThread.Start()
        TcpOpen = True
    End Sub

    Private Sub ConnectionListener()
        Server.Start()
        While True
            Dim client As TcpClient = Server.AcceptTcpClient()
            Dim T As New Thread(AddressOf StartTcpClient)
            T.IsBackground = True
            T.Start(client)
        End While
    End Sub
#End Region

编辑:我对代码进行了一些修改,现在似乎可以按照我的需求工作。

Public Sub StopServer()
    TcpOpen = False
    Server.Stop()
    ServerThread = Nothing
End Sub
Private Sub ConnectionListener()
    Server.Start()
    While True
        If TcpOpen Then
            If Server.Pending Then
                Dim client As TcpClient = Server.AcceptTcpClient()
                Dim T As New Thread(AddressOf StartTcpClient)
                T.IsBackground = True
                T.Start(client)
            Else
                System.Threading.Thread.Sleep(10)
            End If
        Else
            Exit While
        End If
    End While
End Sub
1个回答

0
  1. 连接应该由客户端关闭(而不是服务器)。

  2. 客户端应向服务器发送一个应用程序消息以停止处理。

  3. 服务器应停止处理。

  4. 服务器应执行BeginDisconnect。

  5. 服务器应向客户端发送响应,指示连接可以关闭。

  6. 客户端应关闭连接。

  7. 当发生BeingDisconnect时,服务器应关闭/处理监听器。


当您说“客户端”时,您是指远程一侧吗?如果没有连接,我该如何停止TcpListener? - E_Blue
是的。你有一个客户端(主控)和服务器(从属)。只有在客户端发出命令时,服务器才应执行操作。 - jdweng
1
是的,但问题在于AcceptTcpClient方法是一个阻塞调用,在这种情况下我无法停止服务器。现在我正在尝试使用BeginAcceptTcpClient方法,但仅适用于第一个连接。我认为我需要创建一个线程池,但我正在研究如何做到这一点。所有这些对我来说有点困惑。我目前正在阅读此网页:http://www.vbforums.com/showthread.php?580670-RESOLVED-Closing-a-TcpListener-without-getting-WSACancelBlockingCall-exception - E_Blue
请查看网页:https://msdn.microsoft.com/zh-cn/library/vstudio/w89fhyex(v=vs.100).aspx。这些示例是关于套接字的,但可以替换为任何继承套接字类的类,如TcpClient或TcpListener。 - jdweng

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