如何修复错误“;每个套接字地址通常只允许使用一次”;

本文关键字:许使用 一次 错误 何修复 地址 套接字 | 更新日期: 2023-09-27 18:21:04

我有一个充当服务器(TcpListener)的进程和一个或多个充当客户端(TcpClient)的进程。客户端每1-2秒向服务器发送一次Tcp请求,服务器会以结果消息对其进行响应。

在正常情况下,服务器将使用TcpListener.关闭时停止,但有时服务器会崩溃(无论出于何种原因),然后就不会这样做了。如果我尝试重新启动,那么我会得到以下错误:

"每个套接字地址(协议/网络地址/端口)通常只允许使用一次"

只有当有客户端在运行时,尽管TcpListener已不在(崩溃),但仍在尝试连接时,我才会收到此错误。

在重新启动服务器/TcpListener之前,当我第一次手动关闭/终止所有客户端时,我不会收到这个错误。

我正在寻找一个自动恢复程序来处理这个错误/问题。如何做到这一点?

下面是服务器和客户端的代码示例。

BTW:虽然代码示例在VB.NET中,但我也可以处理C#代码。这就是为什么我用VB和C#标记了这个问题。

服务器/TcpListener的代码示例:

Public Shared Sub Thread_TcpListener_GUI()
    While True
        Dim tcpClient As TcpClient = Nothing
        Dim tcpListener As TcpListener = Nothing
        Try
            tcpListener = New TcpListener(System.Net.IPAddress.Any, 4960)
            tcpListener.ExclusiveAddressUse = False
            Call tcpListener.Start()
            While True
                tcpClient = tcpListener.AcceptTcpClient
                Dim tcpNetworkStream As NetworkStream = tcpClient.GetStream()
                Dim strMessageReceived As String = ""
                'Get received message
                While tcpNetworkStream.DataAvailable
                    Dim byteReceived(tcpClient.ReceiveBufferSize) As Byte
                    tcpNetworkStream.Read(byteReceived, 0, CInt(tcpClient.ReceiveBufferSize))
                    strMessageReceived &= Encoding.UTF8.GetString(byteReceived).Trim(Convert.ToChar(0))
                End While
                'Send response message
                If strMessageReceived <> "" Then
                    Dim strResponse As String = "Received!"
                    Dim byteResponse As Byte() = Encoding.UTF8.GetBytes(strResponse)
                    tcpNetworkStream.Write(byteResponse, 0, byteResponse.Length)
                End If
            End While
        Catch ex As Exception
            Call Console.WriteLine(ex.Message)
        Finally
            Try
                If tcpClient IsNot Nothing Then
                    If tcpClient.Connected Then
                        tcpClient.Close()
                    End If
                End If
            Catch ex As Exception
            End Try
            Try
                If tcpListener IsNot Nothing Then
                    tcpListener.Stop()
                    tcpListener = Nothing
                End If
            Catch ex As Exception
            End Try
            Thread.Sleep(1500)
        End Try
    End While
End Sub

代码示例客户端:

Public Shared Sub TcpClient_SendMessage(ByVal strMessage As String)
    Dim tcpClient As System.Net.Sockets.TcpClient = Nothing
    Dim strResponse As String = ""
    While True
        Try
            tcpClient = New System.Net.Sockets.TcpClient()
            tcpClient.ExclusiveAddressUse = False
            tcpClient.Connect("localhost", 4960)
            Dim tcpNetworkStream As NetworkStream = tcpClient.GetStream()
            'Send message
            Dim byteMessage As Byte() = Encoding.UTF8.GetBytes(strMessage)
            tcpNetworkStream.Write(byteMessage, 0, byteMessage.Length)
            'Get respronse message
            strResponse = ""
            While tcpNetworkStream.DataAvailable
                Dim byteResponse(tcpClient.ReceiveBufferSize) As Byte
                tcpNetworkStream.Read(byteResponse, 0, CInt(tcpClient.ReceiveBufferSize))
                strResponse &= Encoding.UTF8.GetString(byteResponse).Trim(Convert.ToChar(0))
            End While
            'Do something with response here ....
        Catch ex As Exception
            Console.WriteLine(ex.Message)
        Finally
            Try
                If tcpClient IsNot Nothing Then
                    If tcpClient.Connected Then
                        tcpClient.Close()
                        tcpClient = Nothing
                    End If
                End If
            Catch ex As Exception
            End Try
        End Try
    End While
End Sub

如何修复错误“;每个套接字地址通常只允许使用一次”;

线程可以是后台线程,也可以是前台线程。后台线程与前台线程相同,只是后台线程不会阻止进程终止。一旦属于一个进程的所有前台线程都终止了,公共语言运行库就会结束该进程。任何剩余的后台线程都将停止并且不会完成。

这里的问题是,即使应用程序崩溃,侦听器也会继续运行。这是因为它在前台线程上运行。因此,您需要使它成为一个后台线程,以便它与应用程序一起停止。

    Dim receiverThread As Thread
    receiverThread = New Thread(AddressOf Thread_TcpListener_GUI)
    receiverThread.IsBackground = True
    receiverThread.Start()

尝试以这种方式启动线程。希望这会有所帮助。

相关文章: