vb.net TCP 客户端到服务器通信
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35233852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TCP Client to Server communication
提问by Web.11
All I'm looking for is a simple TCPClient/Listner example on Windows Form VB.Net. I'm a newbie and Microsoft TCPClient/Listner class examples are not what I am looking for. All I am looking is for the TCPClient to send a message and for a TCPListener to get the message and to send a message back "I got your message" ?
我正在寻找的只是 Windows Form VB.Net 上的一个简单的 TCPClient/Listner 示例。我是新手,Microsoft TCPClient/Listner 类示例不是我要找的。我所寻找的只是让 TCPClient 发送消息,让 TCPListener 获取消息并发回消息“我收到了你的消息”?
A little help would be great. I have some codes, but is only to send message to server and not back from server to client.. Any help will be very appreciated..
一点帮助会很棒。我有一些代码,但只是将消息发送到服务器而不是从服务器返回到客户端.. 任何帮助将不胜感激..
回答by Visual Vincent
TCP communication is stream-based, which means it doesn't handle any packets. Due to this, messages that you receive might be either partial or lumped together.
TCP 通信是基于流的,这意味着它不处理任何数据包。因此,您收到的消息可能是不完整的,也可能是混在一起的。
You could for example send:
例如,您可以发送:
Hello!
Hello!
How are you?
How are you?
But you might receive:
但您可能会收到:
Hello!How are you?
Hello!How are you?
or:
或者:
Hello!How ar
Hello!How ar
e you?
e you?
(or something similar)
(或类似的东西)
To fix this you must apply something called "length-prefixing". Length-prefixing (or length prefixing) means that before you send a message, you put its length (amount of characters/bytes) in the beginning of it. By doing so, the endpoint will know exactlyhow many bytes to read for each message. Thus there will be no problems with messages being partial or lumped together.
要解决此问题,您必须应用称为"length-prefixing" 的东西。长度前缀(或长度前缀)意味着在您发送消息之前,您将其长度(字符/字节的数量)放在它的开头。通过这样做,端点将确切知道每条消息要读取多少字节。因此,消息不完整或集中在一起不会有任何问题。
This is not the most straightforward thing to do as a beginner, as to get it to work properly on both sides you have to structure your code just right. So I've created two classes that will take care of this for you. See the examples below on how to use them for simple text message-based communication.
作为初学者,这不是最直接的事情,因为要使其在双方正常工作,您必须正确构建代码。所以我创建了两个类来为你处理这个问题。请参阅下面的示例,了解如何将它们用于简单的基于文本消息的通信。
Link to source: http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient.zip
源链接:http: //www.mydoomsite.com/sourcecodes/ExtendedTcpClient.zip
Link to C# source : http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient%20CSharp.zip
链接到 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
编辑 (2019-11-08)
前段时间我做了一个升级版,代码结构和错误处理更好一些。对于那些感兴趣的人,可以在此处下载新代码(仅限 VB.NET):
https://www.mydoomsite.com/sourcecodes/ExtendedTcpClient%202.0.zip
Example usage
示例用法
Note that in those examples Clientdoes notrefer to the client side, but to the TcpClient.
请注意,在这些示例Client中,不是指客户端,而是指TcpClient。
Server side
服务器端
First declare a new variable for
ExtendedTcpClient, and be sure to includeWithEventsin the declaration.Dim WithEvents Client As ExtendedTcpClientThen you will need a
TcpListenerand aTimerto check for incoming connections.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.TimerThen you need to subscribe to the timer's
Tickevent.Private Sub Tmr_Tick(sender As System.Object, e As System.EventArgs) Handles Tmr.Tick End SubIn there you check for incoming connections via the
Listener.Pending()method. When you are to accept a connection you first declare a new instance of theExtendedTcpClient. The class requires to have a form as its owner, in this applicationMeis the current form.
Then you use theExtendedTcpClient.SetNewClient()method withListener.AcceptTcpClient()as its argument to apply theTcpClientfrom the listener. Put this code in theTmr_Ticksub:If Listener.Pending() = True Then Client = New ExtendedTcpClient(Me) Client.SetNewClient(Listener.AcceptTcpClient()) End IfNow the client and server are connected to each other.
Now you need to subscribe to the
PacketReceivedevent of the client. Create a sub like so:Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived End SubAll received data are presented in an array of bytes. In the
PacketReceivedsub you can output the received packet as text into aTextBox. Just check if the packet header isPlainTextand then you can convert the received packets contents (which is an array of bytes, accessed viae.Packet.Contents) to a string and put it in theTextBox.If e.Packet.Header = TcpMessagePacket.PacketHeader.PlainText Then TextBox1.AppendText("Message recieved: " & System.Text.Encoding.Default.GetString(e.Packet.Contents) & Environment.NewLine) End IfSystem.Text.Encoding.Default.GetString()will convert a byte array to normal text.In the
PacketReceivedsub you can also make it send "Message received" to the client.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.Lastly, when closing the form you just need to disconnect the client.
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
首先为 声明一个新变量
ExtendedTcpClient,并确保包含WithEvents在声明中。Dim WithEvents Client As ExtendedTcpClient然后您将需要 a
TcpListener和 aTimer来检查传入连接。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然后你需要订阅定时器的
Tick事件。Private Sub Tmr_Tick(sender As System.Object, e As System.EventArgs) Handles Tmr.Tick End Sub在那里,您可以通过该
Listener.Pending()方法检查传入连接。当您要接受连接时,您首先要声明ExtendedTcpClient. 该类需要有一个表单作为其所有者,在此应用程序中Me是当前表单。
然后您使用ExtendedTcpClient.SetNewClient()方法 withListener.AcceptTcpClient()作为其参数来应用TcpClient来自侦听器的 。将此代码放在Tmr_Tick子中:If Listener.Pending() = True Then Client = New ExtendedTcpClient(Me) Client.SetNewClient(Listener.AcceptTcpClient()) End If现在客户端和服务器相互连接。
现在您需要订阅
PacketReceived客户端的事件。像这样创建一个子:Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived End Sub所有接收到的数据都以字节数组的形式呈现。在
PacketReceivedsub 中,您可以将接收到的数据包作为文本输出到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 IfSystem.Text.Encoding.Default.GetString()将字节数组转换为普通文本。在
PacketReceivedsub 中,您还可以让它向客户端发送“收到的消息”。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.最后,在关闭表单时,您只需要断开与客户端的连接。
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
And that's it for the server side.
这就是服务器端。
Client side
客户端
For the client side you will do pretty much the same as the server side, though you won't be needing a
TcpListenernor aTimer.Dim WithEvents Client As New ExtendedTcpClient(Me) 'The current form as its owner.Connect to the server via the IP and port you've given the listener.
Client.Connect("127.0.0.1", 5555) 'Connects to localhost (your computer) at port 5555.Now if you want to send text to the server you'd do something like this (in for example a button):
Dim MessagePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes(TextBox2.Text), TcpMessagePacket.PacketHeader.PlainText) MessagePacket.Send(Client.Client)TextBox2includes the text you want to send.Lastly, you will need to subscribe to the
PacketReceivedevent here too to check for responses from the server. In there you receive text just like the server does.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
对于客户端,您将执行与服务器端几乎相同的操作,尽管您不需要 a
TcpListener或Timer.Dim WithEvents Client As New ExtendedTcpClient(Me) 'The current form as its owner.通过您为侦听器提供的 IP 和端口连接到服务器。
Client.Connect("127.0.0.1", 5555) 'Connects to localhost (your computer) at port 5555.现在,如果您想向服务器发送文本,您可以执行以下操作(例如在按钮中):
Dim MessagePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes(TextBox2.Text), TcpMessagePacket.PacketHeader.PlainText) MessagePacket.Send(Client.Client)TextBox2包括您要发送的文本。最后,您还需要在
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
And now everything should be working!
现在一切正常!
Link to a complete example project (only client-to-server): http://www.mydoomsite.com/sourcecodes/TCP%20Messaging%20System.zip
链接到完整的示例项目(仅客户端到服务器):http: //www.mydoomsite.com/sourcecodes/TCP%20Messaging%20System.zip
Link to C# example: http://www.mydoomsite.com/sourcecodes/CSharp%20TCP%20Messaging%20System.zip
链接到 C# 示例:http: //www.mydoomsite.com/sourcecodes/CSharp%20TCP%20Messaging%20System.zip
If you want to add more headers to the class (the headers indicate to you what kind of data each packet contains), open TcpMessagePacket.vband add more values in the PacketHeaderenum (located in the region called Constants).
如果要向类添加更多标头(标头向您指示每个数据包包含的数据类型),请打开TcpMessagePacket.vb并在PacketHeader枚举中添加更多值(位于名为 的区域Constants)。
Hope this helps!
希望这可以帮助!
Screenshot from the example project
示例项目的屏幕截图
(Click the image for larger resolution)
(单击图像以获得更大的分辨率)


