TcpClient 不会接收所有数据
Posted
技术标签:
【中文标题】TcpClient 不会接收所有数据【英文标题】:TcpClient doesn't reveive all data 【发布时间】:2021-10-12 11:45:20 【问题描述】:我有一个像这样工作的“信使”应用程序: 客户端向服务器发送消息 -> 服务器将消息转发给其余客户端 -> 客户端读取消息。
服务器始终接收消息,但客户端不接收。
将消息转发到所有客户端(Server/TcpListener)的代码:
public static void SendToAll(TcpClient sender, string message)
// Log the recieved message in the console
Console.WriteLine(message);
// Save the recieved message for new clients
messageLog += message + "\n";
byte[] msg = Encoding.ASCII.GetBytes(message);
foreach (TcpClient client in clients.Keys)
if (client == sender || clients[client] == "") continue;
if (!client.Connected)
clients.Remove(client);
continue;
NetworkStream stream = client.GetStream();
stream.Write(msg, 0, msg.Length);
从服务器读取消息的代码(TcpClient):
byte[] buffer = new byte[1024];
while (true)
using (MemoryStream memoryStream = new MemoryStream())
Int32 bytes = 0;
do
bytes = stream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, bytes);
while (stream.DataAvailable);
Console.WriteLine(Encoding.ASCII.GetString(memoryStream.ToArray()));
Server (image attached)
Client1 (image attached)
Client2 (image attached)
【问题讨论】:
foreach (TcpClient client in clients.Keys)
- 呃,这段代码是否将 TcpClient
对象存储为字典键?如果是这样,你不应该这样做。
我怀疑您的问题是 DataAvailable 返回 false ,因为您的客户端已读取并处理所有可用数据,即使尚未全部到达,并且在准备好之前要求更多,然后在被告知“不可用”时放弃(因为下一个数据仍在传输中)
顺便说一句,使用 SignalR 或一些类似的抽象可能会让你的生活更简单
@Dai 我只是第一次摆弄 TCP,所以我还没有真正考虑到安全性、性能等。如果您可以选择更好的选择,那就太好了。
@CaiusJard 我尝试切换到此代码:Int32 bytesRead = stream.Read(buffer, 0, buffer.Length); string message = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine(message);
还是一样
【参考方案1】:
找到答案了。
问题可能是因为 TCP 速度慢;读取所有流还没有完全完成,并且已经负责读取新数据。
所以我换了
byte[] buffer = new byte[1024];
while (true)
using (MemoryStream memoryStream = new MemoryStream())
Int32 bytes = 0;
do
bytes = stream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, bytes);
while (stream.DataAvailable);
Console.WriteLine(Encoding.ASCII.GetString(memoryStream.ToArray()));
到
// ... Main()
while (true) StartRead();
// ...
public static async void StartRead(NetworkStream stream)
byte[] buffer = new byte[1024];
Int32 bytesRead = await stream.ReadAsync(buffer.AsMemory(0, buffer.Length));
string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine(message);
【讨论】:
以上是关于TcpClient 不会接收所有数据的主要内容,如果未能解决你的问题,请参考以下文章
在 websocket 上使用 TcpClient 接收数据得到 \0\0\0\0
如何处理 TCPClient 中接收到的数据? (德尔福 - 印地)