我也在 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# 中,因为这是我最满意的,对此我深表歉意。 ;)
Client Code
Server Code
我希望这会有所帮助!