【问题标题】:TCP Client to Server communicationTCP 客户端到服务器的通信
【发布时间】:2016-05-16 00:04:13
【问题描述】:

我正在寻找的只是 Windows Form VB.Net 上的一个简单 TCPClient/Listner 示例。我是新手,Microsoft TCPClient/Listner 类示例不是我想要的。我正在寻找的只是让 TCPClient 发送消息,让 TCPListener 获取消息并发送回“我收到你的消息”的消息?

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

【问题讨论】:

  • 除了我的回答,请注意发送和接收数据的是TcpClient,而不是TcpListener。侦听器仅处理传入连接。所以你会在客户端和服务器端都使用TcpClient,但只有服务器端使用TcpListener

标签: vb.net winforms tcp client-server tcpclient


【解决方案1】:

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

例如,您可以发送:

Hello!

How are you?

但您可能会收到:

Hello!How are you?

或:

Hello!How ar

e you?

(或类似的东西)

要解决此问题,您必须应用名为 “长度前缀” 的内容。长度前缀(或长度前缀)意味着在发送消息之前,将其长度(字符/字节的数量)放在它的开头。通过这样做,端点将确切地知道要为每条消息读取多少字节。因此,消息部分或集中在一起不会有任何问题。

对于初学者来说,这并不是最直接的事情,因为要让它在双方都能正常工作,你必须正确地构造你的代码。所以我创建了两个类来为你解决这个问题。请参阅下面的示例,了解如何使用它们进行简单的基于文本消息的通信。

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

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

编辑(2019-11-08)

前段时间我做了一个升级版,代码结构和错误处理更好一些。对于那些感兴趣的人,可以在这里下载新代码(仅限 VB.NET):

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

示例用法

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

服务器端

  1. 首先为ExtendedTcpClient声明一个新变量,并确保 在声明中包含WithEvents

    Dim WithEvents Client As ExtendedTcpClient
    
  2. 然后您将需要TcpListenerTimer 来检查传入连接。

    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 的实例。该类需要有一个 表单作为其所有者,在此应用程序中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。只需检查数据包头是否为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 子中,您还可以使其向客户端发送“收到消息”。

    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. 对于客户端,您将执行与服务器端几乎相同的操作,但您不需要 TcpListenerTimer

    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
    

现在一切都应该正常了!

链接到完整的示例项目(仅限客户端到服务器):http://www.mydoomsite.com/sourcecodes/TCP%20Messaging%20System.zip

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

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

希望这会有所帮助!


示例项目的屏幕截图

(点击图片看大图)

【讨论】:

  • Thnx,这就是我需要的,你做了很好的例子,但在这个例子中,客户端向服务器发送文本,但我需要当服务器收到消息时,才能回复服务器,是这样吗可能吗?
  • @Web.11 是的,该项目不包括,但我的教程包括。请参阅 服务器端 下的第 5 点 :)。只需将该代码放在服务器的PacketReceived 子中即可。
  • 每次在服务器端或客户端调用PacketReceived 事件时,它都表明您已收到一个数据包(如果标头为PlainText,则为消息),所以一切当你收到你应该在那里做的事情时,你需要做。当你要发送一些东西时,你只需声明一个新的TcpMessagePacket,用字节填充它,然后发送它。 - 课程非常优化。我已经使用此代码发送了大文件,没有任何问题。
  • 但请注意: 不要发送太大的数据包。如果您要发送文件或大数据,您应该将其分成几个 8-32 KB 大小的数据包。 --- 说了这么多,如果您需要更多示例/代码内容,请告诉我。 :)
  • 非常感谢,非常好的例子。你能告诉我如何修改它来做到这一点:按下按钮时,客户端连接,发送预定义的消息,并关闭连接。我有多个客户端,并且在按键时他们应该告诉服务器该按钮已被按下,然后让其他人连接免费连接.. 谢谢!
猜你喜欢
  • 2012-04-19
  • 1970-01-01
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 2023-03-18
  • 2012-04-21
  • 1970-01-01
相关资源
最近更新 更多