为什么TCP客户端不发送所有字节?

时间:2018-02-27 10:22:45

标签: c# arrays tcp mono transmission

我通过localhost使用TCP套接字在我的C#/ Mono程序和Raspbian上的Python脚本之间传递数据。数据大约是64k字节。问题是并非所有字节都被发送。发送的最大字节数为49152.我希望它们能够到达一个数据包。

我的代码:

tcpListener = new TcpListener(ip, port);
tcpListener.Start();
tcpClient = tcpListener.AcceptTcpClient();
tcpClient.SendBufferSize = 1000000;
tcpClient.ReceiveBufferSize = 1000000;
networkStream = tcpClient.GetStream();

我已经尝试了以下两种方法来写入数据,但都没有发送所有字节。

tcpClient.Client.Send(byteArray, byteArray.Length, SocketFlags.None);
// OR            
while (!networkStream.CanWrite)
{
     Thread.Sleep(50);
}
networkStream.Write(byteArray, 0, size);

目前,我使用两次连续传输将数据发送到脚本。

这是一个单声道的bug吗?或者我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

之前我遇到过这个问题。 基本上,您需要考虑网络操作的实际工作方式。

当你这样做时

networkStream.Write(byteArray, 0, size);

是的,您正在将其写入流中,但流需要保持打开状态,直到客户端完成数据接收为止。

在我的情况下 - 我发送数据,然后假设networkStream.Read操作已经完成,然后在'Write'端关闭连接。

如果写入的客户端关闭了连接,在他们“认为”文件/数据被写入之后,但在接收者实际上“读取”了数据之前,那么你可以遇到部分数据是丢失。

解决此问题的方法是使用您的网络创建协议。

一种常见的策略是测量您希望发送的数据量,然后将其作为长变量发送到有效负载之前。 然后,接收器将知道预期有多少数据,并将从流中读取该数据量。 完成后,接收方应该让客户知道他们已经收到了所有数据。

写入客户端可以“等待”此确认消息,以保持流唤醒。

我使用的早期解决方案之一是:

while (client.IsConnected())
       {
            System.Threading.Thread.Sleep(100);
       }

发送大文件后立即发送。 然后我依靠接收器自己终止连接。 如果连接终止,在我的情况下,它将是我需要知道文件已完成传输的信号。