TCP 客户端到服务器通信

TCP Client to Server communication

我要找的只是 Windows 表格 VB.Net 上的一个简单 TCPClient/Listner 示例。我是新手,Microsoft TCPClient/Listner class 示例不是我要找的。我正在寻找的只是让 TCPClient 发送消息,让 TCPListener 获取消息并发回消息 "I got your message" ?

如果有一点帮助就好了。我有一些代码,但只是将消息发送到服务器,而不是从服务器返回到客户端。 任何帮助将不胜感激..

TCP 通信是 stream-based,这意味着它不处理任何数据包。因此,您收到的消息可能是部分消息或集中在一起的消息。

例如,您可以发送:

Hello!

How are you?

但您可能会收到:

Hello!How are you?

或:

Hello!How ar

e you?

(或类似的东西)

要解决此问题,您必须应用名为 "length-prefixing" 的东西。 Length-prefixing(或长度前缀)表示在发送消息之前,将其长度(characters/bytes 的数量)放在消息的开头。通过这样做,端点将确切知道每条消息要读取多少字节。因此,消息被部分或集中在一起不会有问题。

作为初学者,这不是最简单的事情,因为要让它在双方都能正常工作,您必须恰到好处地构建代码。所以我创建了两个 classes 来为您解决这个问题。请参阅下面的示例,了解如何将它们用于简单的文本 message-based 通信。

Link 来源:http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient.zip

Link 到 C# 源代码:http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient%20CSharp.zip

EDIT (2019-11-08)

Some time ago I made an upgraded version of this with a bit better code structure and error handling. For those of you interested, the new code can be downloaded here (VB.NET only):

https://www.mydoomsite.com/sourcecodes/ExtendedTcpClient%202.0.zip

用法示例

请注意,在这些示例中 Client 不是 指的是 客户端 ,而是指 TcpClient.

服务器端

  1. 首先为ExtendedTcpClient声明一个新变量,一定要 在声明中包含 WithEvents

    Dim WithEvents Client As ExtendedTcpClient
    
  2. 然后您将需要一个 TcpListener 和一个 Timer 来检查传入连接。

    Dim Listener As New TcpListener("0.0.0.0", 5555) 'Listen for any connection on port 5555.
    Dim WithEvents Tmr As New System.Windows.Forms.Timer
    
  3. 那么你需要订阅定时器的Tick事件。

    Private Sub Tmr_Tick(sender As System.Object, e As System.EventArgs) Handles Tmr.Tick
    
    End Sub
    

    在那里,您可以通过 Listener.Pending() 方法检查传入连接。当你要接受一个连接时,你首先要声明一个新的 ExtendedTcpClient 的实例。 class 需要有一个 表单作为其所有者,在此应用程序中 Me 是当前表单。
    然后你使用 ExtendedTcpClient.SetNewClient() 方法 Listener.AcceptTcpClient() 作为参数应用 TcpClient 来自听众。将此代码放在 Tmr_Tick sub:

    If Listener.Pending() = True Then
        Client = New ExtendedTcpClient(Me)
        Client.SetNewClient(Listener.AcceptTcpClient())
    End If
    

    现在客户端和服务器已经相互连接了。

  4. 现在您需要订阅 PacketReceived 的事件 客户。像这样创建一个子:

    Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived
    
    End Sub
    

    所有接收到的数据都以字节数组的形式呈现。 在 PacketReceived 子中,您可以将接收到的数据包作为文本输出到 TextBox 中。只需检查数据包 header 是否为 PlainText 然后 您可以转换接收到的数据包内容(这是一个数组 字节,通过 e.Packet.Contents) 访问到一个字符串并将其放入 TextBox.

    If e.Packet.Header = TcpMessagePacket.PacketHeader.PlainText Then
        TextBox1.AppendText("Message recieved: " & System.Text.Encoding.Default.GetString(e.Packet.Contents) & Environment.NewLine)
    End If
    

    System.Text.Encoding.Default.GetString() 将字节数组转换为普通文本。

  5. PacketReceived子中你也可以让它发送"Message received"到客户端。

    Dim ResponsePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes("Message received."), TcpMessagePacket.PacketHeader.PlainText)
    ResponsePacket.Send(Client.Client) 'Get the ExtendedTcpClient's underlying TcpClient.
    
  6. 最后,关闭表单时,您只需断开客户端即可。

    Private Sub ServerWindow_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If Client IsNot Nothing Then Client.Disconnect()
    End Sub
    

服务器端就这些了。


客户端

  1. 对于客户端,您将做与服务器端几乎相同的事情,尽管您不需要 TcpListener 也不需要 Timer.

    Dim WithEvents Client As New ExtendedTcpClient(Me) 'The current form as its owner.
    
  2. 通过您为侦听器提供的 IP 和端口连接到服务器。

    Client.Connect("127.0.0.1", 5555) 'Connects to localhost (your computer) at port 5555.
    
  3. 现在如果你想发送文本到服务器你会做这样的事情(例如一个按钮):

    Dim MessagePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes(TextBox2.Text), TcpMessagePacket.PacketHeader.PlainText)
    MessagePacket.Send(Client.Client)
    

    TextBox2 包含您要发送的文本。

  4. 最后,您还需要在此处订阅 PacketReceived 事件以检查来自服务器的响应。在那里你可以像服务器一样接收文本。

    Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived
        If e.Packet.Header = TcpMessagePacket.PacketHeader.PlainText Then
            TextBox1.AppendText(System.Text.Encoding.Default.GetString(e.Packet.Contents) & Environment.NewLine) 'Prints for example "Message received." from the server.
        End If
    End Sub
    

现在一切正常!

Link 到完整的示例项目(仅 client-to-server):http://www.mydoomsite.com/sourcecodes/TCP%20Messaging%20System.zip

Link 到 C# 示例:http://www.mydoomsite.com/sourcecodes/CSharp%20TCP%20Messaging%20System.zip

如果你想在class中添加更多的header(header告诉你每个数据包包含什么样的数据),打开TcpMessagePacket.vb并在 PacketHeader 枚举中添加更多值(位于名为 Constants 的区域)。

希望对您有所帮助!


示例项目的屏幕截图

(点击图片查看大图)