【发布时间】:2015-11-23 02:20:38
【问题描述】:
我正在尝试编写一个小型客户端,它将在某个端口上侦听服务器。当我运行我的代码时,它似乎挂起,那么它只会给我第一条消息,之后就不再收到了吗?我在这里破坏了我的大脑。任何帮助表示赞赏。
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
谢谢
大卫
【问题讨论】:
-
gSocket.Receive 应该在一个循环中。如果消息是 10k,您一次只能收到 1k。简而言之,调用一次函数并不能保证收到完整的消息。另外,您的评论是错误的 vMessageLength 不是 1025 字节,而是 1g。 vBuffer 数组会很大。
-
谢谢你:-) 你的意思是一个while循环吗?对不起,但不是很有经验...
-
是的,您需要循环直到收到所有信息。这意味着您需要接收固定数量的字节或具有包含信息大小的数据包头。