简体   繁体   English

如何使用TcpClient读取直到另一端关闭或我们在.Net中停止

[英]How to read with a TcpClient until the other side closes or we stop in .Net

I have a listener that returns a TcpClient that must read data until the other side closes or until we stop. 我有一个侦听器,该侦听器返回一个TcpClient,该TcpClient必须读取数据,直到另一端关闭或停止为止。

I have created a simple Form with two buttons. 我创建了一个带有两个按钮的简单表单。 One starts one connection and the other stops it. 一个启动一个连接,另一个停止它。

The problem is that when I have a IOException due to the timeout of the Read the socket is closed and I cannot communicate with it again. 问题是当由于读取超时而发生IOException时,套接字已关闭,我无法再次与其通信。 I cannot reconnect it as is the other side the one to establish the connection. 我无法重新建立连接,因为另一端是建立连接的连接。

Just execute the code and telnet to the port 502, wait one second and you will see the problem. 只需执行代码和telnet到端口502,等待一秒钟,您将看到问题。

How would you do that? 你会怎么做?

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")
            Else
                MsgBox(dataLength.ToString() & " bytes received")
            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

This question is related to the question: How to close a TcpClient when the other end has been closed in .NET? 该问题与以下问题有关: 在.NET中已关闭另一端时,如何关闭TcpClient?

FINALLY: The real problem is that to know when a client has closed the connection I must do a Read and check for a return of 0. If the Read has infinite Timeout the call will block and I will not be able to end the application until the Read returns something, if the read has a finite Timeout I can have a TimeoutException and then the Socket will be closed. 最终:真正的问题是,要知道客户端何时关闭连接,我必须执行一次读取并检查返回值是否为0。如果读取具有无限超时,则调用将被阻塞,直到等到我才能结束应用程序读取返回一些信息,如果读取具有有限的超时,则我可以有一个TimeoutException,然后套接字将关闭。 So ... HOW THE HELL I'M SUPPOSED TO KNOW WHEN THE OTHER PART HAS CLOSED THE CONNETION? 那么……当其他部分关闭时,我该如何知道呢? I can not believe that something so "easy" is so hard. 我不敢相信如此“轻松”的事情是如此艰难。

I've found the solution. 我找到了解决方案。 What has to be done is to do a Read() with timeout set to infinite and when you need to unblock that Read call you just need to call to Close() and the Read() will unblock. 必须要做的是将Read()的超时设置为无穷大,并且当您需要取消阻止该Read调用时,只需调用Close()即可,而Read()将会取消阻止。

Rather than trying to Read from the stream and catch a TimeoutException , you could check the Available property to know whether there is data to be read. 与尝试从流中Read并捕获TimeoutException ,您可以检查Available属性来确定是否有要读取的数据。 That way the TimeoutException won't happen, and you will still be able to reuse the TcpClient 这样, TimeoutException就不会发生,并且您仍然可以重用TcpClient

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM