有人可以告诉我为什么我的服务器在我的rclient连接并尝试发送数据时锁定了吗?
如果我发表评论:
Dim bytes(rclient.ReceiveBufferSize) As Byte
rstream.Read(bytes, 0, CInt(rclient.ReceiveBufferSize))
RString = Encoding.ASCII.GetString(bytes)
TextBox2.Text = RStringcode here
并且只是
TextBox2.Text = ("Remote connected")
服务器选择连接的客户端,所以它必须是我用.read?
做的事情Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Imports System.IO.Ports
Dim tclient As New TcpClient
Dim tstream As NetworkStream
Dim rclient As New TcpClient
Dim rstream As NetworkStream
Dim sArray() As String
Dim Tricopter As New TcpListener(2000)
Dim Remote As New TcpListener(2001)
Dim myVal As String
Dim TricopterThread As New Thread(AddressOf TricopterThreadSub)
Dim RemoteThread As New Thread(AddressOf RemoteThreadSub)
Dim tre(tclient.ReceiveBufferSize) As Byte
Dim TState = False
Dim RState = False
Dim SerialSwitch = False
Dim Toggle = False
Dim TString As String
Dim RString As String
Dim Remo(rclient.ReceiveBufferSize) As Byte
Dim TSendText() As Byte
Private Sub RemoteThreadSub()
rclient = Remote.AcceptTcpClient
rstream = rclient.GetStream
RState = True
End Sub
Private Sub TricopterThreadSub()
tclient = Tricopter.AcceptTcpClient
tstream = tclient.GetStream
TState = True
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CheckForIllegalCrossThreadCalls = False
Tricopter.Start()
Remote.Start()
Timer1.Start()
TricopterThread.Start()
RemoteThread.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
myVal = ">" & TrackBar1.Value & "," & TrackBar2.Value & "," & TrackBar3.Value & "," & TrackBar4.Value & "/n"
Try
If TState = False Then
TextBox1.Text = ("No tricopter connected")
Else
TextBox1.Text = myVal
If Toggle = False Then
TSendText = Encoding.ASCII.GetBytes(myVal)
End If
If Toggle = True Then
TSendText = Encoding.ASCII.GetBytes(RString)
End If
tstream.Write(TSendText, 0, TSendText.Length)
End If
If RState = False Then
TextBox2.Text = ("No Remote connected")
Else
' TextBox2.Text = ("Remote connected")
Dim bytes(rclient.ReceiveBufferSize) As Byte
rstream.Read(bytes, 0, CInt(rclient.ReceiveBufferSize))
RString = Encoding.ASCII.GetString(bytes)
TextBox2.Text = RString
End If
Catch ex As Exception
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If Toggle = False Then
CheckBox1.CheckState = 1
Toggle = True
Else
CheckBox1.CheckState = 0
Toggle = False
End If
End Sub
结束班
答案 0 :(得分:0)
编辑:对于那些已经下载/测试过的人,我对课程进行了修正,因此如果您要再次使用它们,则需要重新下载这些来源。
如果您想要执行正确的数据传输,您需要使用比仅仅读取随机数据更可靠的方法。正如 usr 所指出的那样:TcpClient.ReceiveBufferSize
属性不会告诉您要接收的数据量,以及发送给您的数据量。 ReceiveBufferSize
只是一个变量,表示每次读取传入数据时预计会获得多少字节。有关详情,请阅读有关主题的MSDN page。
至于数据传输,我创建了两个类,它们将为您进行长度前缀数据传输。只需将它们导入您的项目,您就可以立即开始使用它们。链接:http://www.mydoomsite.com/sourcecodes/ExtendedTcpClient.zip
服务器端
首先为ExtendedTcpClient
声明一个新变量,并确保
在声明中包含WithEvents
。
Dim WithEvents Client As ExtendedTcpClient
然后你只需要使用普通TcpListener
来检查
传入连接。 TcpListener.Pending()
方法可以
例如,检查了一个计时器。
当您接受新的TcpClient
时,首先声明一个新的ExtendedTcpClient
Me
的实例。这堂课要求有一个
作为其所有者的表单,在此应用程序中ExtendedTcpClient.SetNewClient()
是当前表单
然后,使用Listener.AcceptTcpClient()
方法
TcpClient
因为它适用于
来自听众的If Listener.Pending() = True Then
Client = New ExtendedTcpClient(Me)
Client.SetNewClient(Listener.AcceptTcpClient())
End If
。
ExtendedTcpClient
之后你将不再需要计时器了
PacketReceived
有自己的线程来检查数据。
现在您需要订阅Private Sub Client_PacketReceived(sender As Object, e As ExtendedTcpClient.PacketReceivedEventArgs) Handles Client.PacketReceived
End Sub
事件
客户。像这样创建一个子:
TextBox
在那里,您可以将收到的数据包作为文本输出到
一个PlainText
。只需检查数据包标头是否为e.Packet.Contents
然后
你可以转换收到的数据包内容(这是一个数组
通过TextBox
访问的字节到字符串并将其放入
If e.Packet.Header = TcpMessagePacket.PacketHeader.PainText Then
TextBox1.AppendText("Message recieved: " & System.Text.Encoding.Default.GetString(e.Packet.Contents) & Environment.NewLine)
End If
。
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
最后,关闭表单时,您只需要断开客户端连接。
TcpClient
这就是服务器端。
客户端
对于客户端,您只需要正常的Dim Client As New TcpClient
(,除非您也不想在那里接收数据)。
Client.Connect("127.0.0.1", 5555) 'Connects to localhost (your computer) at port 5555.
然后通过您给予监听器的IP和端口连接到服务器。
Dim MessagePacket As New TcpMessagePacket(System.Text.Encoding.Default.GetBytes(TextBox2.Text), TcpMessagePacket.PacketHeader.PainText)
MessagePacket.Send(Client) 'Client is the regular TcpClient.
现在,如果您想将纯文本发送到服务器,您可以执行以下操作:
TcpMessagePacket.vb
现在一切都应该正常工作!
链接到完整的示例项目:http://www.mydoomsite.com/sourcecodes/TCP%20Messaging%20System.zip
如果您想在课程中添加更多标题,只需打开PacketHeader
并在Constants
枚举(位于名为onCreateOptionsMenu
的区域)中添加更多值。
希望这有帮助!
(点击图片查看大图)
答案 1 :(得分:0)
您假设读取返回特定数量的数据,例如ReceiveBufferSize
。事实并非如此。读取返回至少一个字节,即全部。
为了澄清,TCP不支持基于邮件的传输。
正确的阅读方式取决于协议。如果知道预期的确切字节数,则需要在循环中读取,直到接收到这么多字节(或者使用BinaryReader为您执行此操作)。
对于基于行的协议,您可以使用StreamReader.ReadLine
再次自动循环。
ReceiveBufferSize
与可用或将来的数据完全无关。
DataAvailable
现在可以无阻塞地读取多少数据。但可能会有更多数据出现。使用它几乎总是一个bug。即使数据在1ms之后出现,也可能随时返回0。