【问题标题】:.NET TcpClient/TcpListener only receiving first message.NET TcpClient/TcpListener 只接收第一条消息
【发布时间】:2014-06-11 03:03:11
【问题描述】:

我有一个使用 TCP 发送/接收消息的简单程序。出于某种原因,它可以很好地接收第一条消息,但除非我关闭并重新连接客户端,否则服务器不会收到来自该客户端的第一条消息之外的任何消息。我提供了下面代码的精简版本(所以请原谅缺乏异常处理)。

Private TCPWriter As TcpClient
Private TCPListener As TcpListener

Private Sub Send(sender As Object, e As RoutedEventArgs)
    Connect()
    WriteTextToServer(MessageBox.Text)
End Sub

Private Sub Connect()
    If TCPWriter Is Nothing Then
        TCPWriter = New TcpClient
    End If

    If Not TCPWriter.Connected Then
        TCPWriter.Connect(System.Net.IPAddress.Parse(IPBox.Text), PortBox.Text)
        TCPWriter.NoDelay = True
    End If
End Sub

Private Sub WriteTextToServer(inMsg As String)
    Dim data() As Byte = Encoding.ASCII.GetBytes(inMsg + vbCrLf)
    Dim ns As NetworkStream = TCPWriter.GetStream()

    If ns.CanWrite Then
        ns.Write(inMsg, 0, inMsg.Length - 1)
    End If
End Sub

Private Sub ReadNewDataFromClient(ByVal inStatus As IAsyncResult)
    Dim clientSocket As TcpClient
    Dim datalen As Integer
    Dim buf() As Byte
    Dim message As String

    clientSocket = CType(inStatus.AsyncState, TcpListener).EndAcceptTcpClient(inStatus)
    clientSocket.ReceiveTimeout = 5000

    datalen = clientSocket.Available
    If datalen > 0 Then
        'get all data at once ...
        buf = New Byte(datalen - 1) {}
        clientSocket.GetStream().Read(buf, 0, buf.Length)

        message = Encoding.ASCII.GetString(buf, 0, buf.Count - 2)
        Me.Dispatcher.Invoke(Sub() ReadNewDataFromClients.Add(ReadNewDataFromClients.Count.ToString + ": " + message))
    End If

    TCPListener.BeginAcceptTcpClient(New AsyncCallback(AddressOf ReadNewDataFromClient), Nothing)
End Sub

如果我将 Connect() 方法更改为以下代码,它会起作用,但似乎不是正确的方法。

Private Sub Connect()
    If TCPWriter IsNot Nothing Then
        TCPWriter.close
        TCPWriter = nothing
        Threading.Thread.Sleep(1000)
    End If

    TCPWriter = New TcpClient

    If Not TCPWriter.Connected Then
        TCPWriter.Connect(System.Net.IPAddress.Parse(IPBox.Text), PortBox.Text)
        TCPWriter.NoDelay = True
    End If
End Sub

我做错了什么?

【问题讨论】:

    标签: .net vb.net tcpclient tcplistener


    【解决方案1】:

    您正在使用BeginAcceptTcpClient 接收下一条“消息”,这用于接受新连接(这就是在您断开/重新连接每条消息时它起作用的原因)。您应该只使用Read/BeginRead 来阅读下一条消息。

    话虽如此,您还需要了解TCP是一个协议,因此它没有“消息”的概念,也许最重要的是,它们之间没有可靠的对应关系发送方对Write 的调用次数以及接收方读取发送数据所需的对Read 的调用次数。

    如果您想将 TCP 用于离散消息,则需要发送数据,以便可以将其拆分为接收端的单独消息。这通常是通过在消息前面加上一个固定大小(例如 4 个字节)的长度指示符来“构建”消息来完成的。

    您还需要确保观察Read 方法的返回值,该值将指示实际上读入缓冲区的字节数。

    【讨论】:

    • BeginAcceptTcpClient/EndAcceptTcpClient 组合是否不会将流分解为可以视为消息的内容(数据不会从客户端快速发送)? ReadNewDataFromClient() 方法在运行时只调用一次,我希望在客户端向流中写入数据时调用它。
    • @AXG1010 - 不,TcpListenerBegin/EndAcceptTcpClient 方法用于接受来自客户端的(新)连接。连接后,通过连接进行的通信由TcpClients 本身的Write 方法执行。
    • 感谢您的帮助!我能够让它工作,而不必经常连接/断开连接。
    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多