我创建了一个TCP服务器,它可以同时与多个客户端通信,但我似乎无法使它们稳定。当其中一个客户端向服务器发送100个数据包时,服务器只接收其中一些数据包。
Here's the client code in PasteBin。它显示了客户端如何连接到服务器,然后在For循环中将100条消息发送到服务器。
And here's how the server handles the connection。我无法粘贴完整的源代码,因为它有数百行,所以请告诉我它是否缺少任何必需的部分,我也会上传它们。
答案 0 :(得分:1)
我也在reddit上回答了你的问题,但我想我会在这里回复以防其他人在搜索这类东西。
服务器处理读取的方式有两个问题。首先,您的客户端对象的构造函数:
Public Sub New(ByVal client As TcpClient)
'New client connects
Me.client = client
client.GetStream().BeginRead(New Byte() {0}, 0, 0, AddressOf Read, Nothing)
End Sub
BeginRead希望您以可以传递给回调方法的方式收集数据;在这种情况下“阅读”。通常,这是通过创建一个新对象来保存此异步操作的“状态”,并将其作为最后一个参数传递给BeginRead来完成的。这里的方法调用是创建一个新的字节数组,但是没有对它进行引用以作为方法的最后一个参数传入。这意味着此调用读取的数据在读取后将消失,因为它永远不会传递给存储它的方法。
其次,你的阅读操作:
Public Sub Read(ByVal ar As IAsyncResult)
Dim reader As New StreamReader(client.GetStream())
clientPacket &= reader.ReadLine()
client.GetStream().BeginRead(New Byte() {0}, 0, 0, AddressOf Read, Nothing)
End Sub
由于您没有传入异步调用中读取的数据,因此您在此处创建一个新的StreamReader以从客户端提取更多数据。这不是异步方法调用。您的reader.ReadLine()调用将阻塞,直到遇到换行符,此时数据将附加到clientPacket。然后再次调用BeginRead,问题与上述相同,这意味着您将丢失更多数据。
此外,您永远不会通过在流上调用EndRead()来清除AsyncResult对象,当CLR用完异步操作的工作线程时,最终会导致资源不足。
以下是我实施此类任务的方式示例。这是在C#,因为这是我最舒服的,所以很抱歉。 ;)
我希望这有帮助!