gpt4 book ai didi

vb.net - TCP 客户端未收到所有消息

转载 作者:可可西里 更新时间:2023-11-01 02:54:12 28 4
gpt4 key购买 nike

我正在尝试编写一个小型客户端,它将在某个端口上监听服务器。当我运行我的代码时,它似乎挂起,然后它只会给我第一条消息,之后就不再收到了?我在这里伤脑筋。任何帮助表示赞赏。

    Option Strict On

Imports System.Net
Imports System.Net.Sockets
Imports System.Text

Public Class Form1

'Form Controls.
Private lblPort As New Label
Private txtPort As New TextBox
Private lblIp As New Label
Private txtIp As New TextBox
Private lblSend As New Label
Private txtSend As New TextBox
Private WithEvents btnConnectSendReceive As New Button
Private lblReceived As New Label
Private lvwReceived As New ListView
Private txtBoxrecieved As New RichTextBox

'Global Objects.
Private gSocket As Socket = Nothing

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

'Setup form controls.
With Me
.Text = "SplitPackManagerTest"
.Controls.Add(lblPort)
.Controls.Add(txtPort)
.Controls.Add(lblIp)
.Controls.Add(txtIp)
.Controls.Add(lblSend)
.Controls.Add(txtSend)
.Controls.Add(btnConnectSendReceive)
.Controls.Add(lblReceived)
.Controls.Add(lvwReceived)
.Controls.Add(txtBoxrecieved)
.Height = 600
End With
With lblPort
.Text = "Port:"
.Location = New Point(12, 12)
.AutoSize = True
End With
With txtPort
.Text = "3001" 'Same port that server is listening on.
.Location = New Point(100, 12)
End With
With lblIp
.Text = "IP:"
.Location = New Point(12, 42)
.AutoSize = True
End With
With txtIp
.Text = "127.0.0.1" 'Loop-back IP address (localhost).
.Location = New Point(100, 42)
End With
With lblSend
.Text = "Send:"
.Location = New Point(12, 72)
.AutoSize = True
End With
With txtSend
.Text = Chr(2) & "(login (term-id 2))" & Chr(3)
.Location = New Point(100, 72)
End With
With btnConnectSendReceive
.Text = "Connect"
.Location = New Point(12, 122)
.Width = 260
End With
With lblReceived
.Text = "Received Bytes:"
.Location = New Point(12, 182)
.AutoSize = True
End With
With lvwReceived
.Height = 100
.Dock = DockStyle.Bottom
.View = View.Details
.GridLines = True
.FullRowSelect = True
.MultiSelect = False
.Scrollable = True
.Columns.Add("Dec")
.Columns.Add("Hex")
.Columns.Add("Chr")
For Each vCol As ColumnHeader In .Columns
vCol.Width = CInt(Math.Floor(.Width / .Columns.Count)) - CInt(Math.Floor(30 / .Columns.Count))
Next
End With
With txtBoxrecieved
.Height = 200
.Dock = DockStyle.Bottom
.ScrollBars = RichTextBoxScrollBars.Both
End With
End Sub

Private Function ConnectSendReceive(ByVal pSendData As Byte(), ByVal pIp As String, ByVal pPort As Integer) As Byte()

'Try creating IP endpoint.
If String.IsNullOrEmpty(pIp) Then Return Nothing
If Not IPAddress.TryParse(pIp, Nothing) Then Return Nothing
Dim vIp As IPAddress = IPAddress.Parse(txtIp.Text)
Dim vEndPoint As New IPEndPoint(vIp, CInt(txtPort.Text))

'Timeout will be 0.5 seconds.
Dim vTimeout As Integer = 500000

'For our little example, we expect all messages to be 1024 bytes or below (arbitrary amount).
Dim vMessageLength As Integer = 1002400000

'Remember, when dimensioning arrays, the integer specified is the upper bounds, not the length.
Dim vServerResponse As Byte() = Nothing

'Initiate socket.
Dim gSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

'Connect.
Try
gSocket.Connect(vEndPoint)

Catch ex As Exception
Return Nothing
End Try
If Not gSocket.Connected Then Return Nothing

'Send.
'Socket.SendTimeout = vTimeout
gSocket.Send(pSendData)
txtBoxrecieved.AppendText("Sending.. " & txtSend.Text)


'Receive response.
'Socket.ReceiveTimeout = vTimeout
Dim vBuffer(vMessageLength - 1) As Byte
Dim vNumOfBytesReceived As Integer = 0
Try
vNumOfBytesReceived = gSocket.Receive(vBuffer, 0, vMessageLength, SocketFlags.None)
Catch ex As Exception
Return Nothing
End Try

'Return received bytes.
ReDim vServerResponse(vNumOfBytesReceived - 1)
Array.Copy(vBuffer, vServerResponse, vNumOfBytesReceived)

'Disconnect (since we're using a "Using" statement, the socket will be disconnected here without us explicitly doing it).


Return vServerResponse
End Function

Private Sub btnConnectSendReceive_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnectSendReceive.Click

'Send message and get response from server.
Dim vServerResponse As Byte() = ConnectSendReceive(Encoding.ASCII.GetBytes(txtSend.Text), txtIp.Text, CInt(txtPort.Text))

'Did we receive a response?
If vServerResponse Is Nothing Then MessageBox.Show("Server not reachable / Received no response from server.") : Exit Sub

'Do something with response.
For Each vByte As Byte In vServerResponse
Dim vLvi As New ListViewItem
With vLvi

'Decimal column.
.Text = vByte.ToString

'Hexidecimal column.
.SubItems.Add(vByte.ToString("X2"))

'Character column.
.SubItems.Add(ChrW(vByte))
End With
With lvwReceived
.Items.Add(vLvi)
.EnsureVisible(.Items.Count - 1)
End With

Next
txtBoxrecieved.AppendText(UnicodeBytesToString(vServerResponse))
End Sub
Private Function UnicodeBytesToString(
ByVal bytes() As Byte) As String

Return System.Text.Encoding.ASCII.GetString(bytes)
End Function
End Class

谢谢

大卫

最佳答案

您需要了解对话双方的情况。为此,您需要使用 Wireshark 等工具进行监听。下载 Wireshark 并学习使用它。

我倾向于同意 the_lotus 的原因是您分配的非常大的缓冲区(忽略可能的大小错误)意味着您期望相当大的响应。数据包有效载荷最大可达 64KB,但这并不常见,即使发生这种情况,协议(protocol)也允许在途中进行分段。

因此,如果数据被拆分成多个数据包,您将需要继续阅读,直到获得完整的有效载荷。这可能需要在流中寻找边界标记,如果有可能通过同一连接接收更多有效载荷,您需要以允许您累积其余部分的方式保留下一个有效载荷的开始。

如果您这样做,您可能会看到一个包含部分负载的完整数据包,正如 the_lotus 在我仍在撰写本文时发布的评论中所描述的那样。

我认为他可能是对的,但也可能是错的,像 Wireshark 这样的工具可以让您找到答案,而不是盲目地猜测和修改您的代码来验证您的假设。

您使用的 I/O 样式称为轮询。有时有必要那样做,例如嵌入式系统通常不支持任何更复杂的东西,没有空间容纳它。但是在具有完整 .NET 框架的系统上,您确实应该使用 IOCP .对于单用户应用程序来说,这并不是绝对必要的,但如果您养成正确的习惯,就不会产生可伸缩性问题。

好的,至于响应被截断的原因,在检查了您的代码(VB 使我的眼睛受伤)之后,我几乎可以肯定 the_lotus 是正确的。您正在从套接字中读取一次,然后关闭它而没有任何尝试检查您是否有完整的响应或任何尝试读取更多数据。

这看起来像是大学一年级的作业,所以大概您有某种规范。要确定您是否有完整的回复,您需要了解以下任一内容

  • 预期的负载长度
  • 有效负载中数据的位置和结构告诉您剩余的长度(或有时是总数据包的大小)
  • 有效载荷结束标记,这将是保证不会以其他方式出现在有效载荷中的特定字节序列。

一些伪代码

open the connection
while not CheckForCompletePayload(buffer)
read some data and append it to your buffer
close the connection.

关于vb.net - TCP 客户端未收到所有消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32270751/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com