Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当另一端已在.NET中关闭时,如何关闭TCP客户端?_.net_Tcpclient - Fatal编程技术网

当另一端已在.NET中关闭时,如何关闭TCP客户端?

当另一端已在.NET中关闭时,如何关闭TCP客户端?,.net,tcpclient,.net,Tcpclient,我有一个处理tcpclient的类。班级应该做的是: while the other end has not done a graceful close or we are stopping { receive a request process it send response } 由于我不知道其他客户端何时会发送请求,因此我无法在设置了超时的情况下进行读取,因此我目前拥有的是: While Not Me.Sto

我有一个处理tcpclient的类。班级应该做的是:

    while the other end has not done a graceful close or we are stopping
    {
        receive a request
        process it
        send response
    }
由于我不知道其他客户端何时会发送请求,因此我无法在设置了超时的情况下进行读取,因此我目前拥有的是:

    While Not Me.Stopping()
        Try
            If tcpClient.Available >= My.Settings.minimumModBusTcpFrameSize Then
                processer = New MessageProcesser(Me, tcpClient)
                processer.ProcessMessage()
            End If
        Catch ex As TimeoutException
            ''#Do not nothing, the current message will timeout on origin too.
        End Try
    End While
这种方法的问题是,我永远不知道客户机何时对Close()进行了远程调用


有办法解决这个问题吗?

我不明白你为什么不能在超时的情况下执行
读取
。。。如果读取超时,您可以重试,而如果
read
返回0,则连接已关闭


编辑:是的,我已经在这里证实了这种行为——进一步的阅读似乎确实失败了。真奇怪。。。我在这里留下我的答案,因为我认为这是一个合适的答案-希望在某个时候我会有时间再次调查它。

Jon已经回答了,但是如果你控制了客户端,那么你也可以添加一个表示“请关闭连接”的请求,这样你就可以尝试“优雅地关闭”,只需使用Jon的“自动检测”如果客户端未能整齐地关闭连接,请进行处理。

我有一个类似的情况,但与udpclient有关。我正在捕获SocketException以确定远程端点是否不再可用:

    While True
        Try
            Dim RecievedBytes As Byte() = udp.Receive(mRemoteIP)
            mMessage = System.Text.Encoding.ASCII.GetString(RecievedBytes)
            RaiseEvent MessageRecieved()
        Catch ex As Sockets.SocketException
            MsgBox("Your firewall may be blocking you from recieving messages")
        End Try
    End While

只是一个测试,以显示在实现Jon Skeet答案时发现的问题:

Public Class Form1

Private m_listener As Net.Sockets.TcpListener
Private m_client As Net.Sockets.TcpClient
Private m_stopping As Boolean

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim data As Byte()
    Dim dataLength As Integer

    ReDim data(512)

    m_listener = New Net.Sockets.TcpListener(Net.IPAddress.Any, 502)
    m_listener.Start()
    m_client = m_listener.AcceptTcpClient()

    m_client.GetStream().ReadTimeout = 1000
    m_client.GetStream().WriteTimeout = 1000

    While Not m_stopping
        Try
            dataLength = m_client.GetStream.Read(data, 0, data.Length)
            If dataLength = 0 Then
                MsgBox("Disconnected")
            End If
        Catch ex As Exception When TypeOf (ex) Is TimeoutException OrElse (Not ex.InnerException Is Nothing AndAlso TypeOf (ex.InnerException) Is Net.Sockets.SocketException AndAlso DirectCast(ex.InnerException, Net.Sockets.SocketException).ErrorCode = 10060)
            ''# Just retry
        End Try
    End While
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    m_stopping = True
End Sub
End Class

如果您与Telnet客户端连接,您将收到InvalidOperationException,因为套接字已在超时时间(1秒)后关闭。

解决方案是这个问题:


我发现Read和IOException而不是TimeoutException有问题。我正在调查并将返回结果。看起来当我超时时,TcpClient断开连接,套接字关闭,因此我无法再次重试读取。