0

我的问题是,当我通过本地 LAN 网络传输连续的数据流时,有时随机字节会在此过程中丢失。

就像现在一样,代码设置为在局域网上流式传输大约 1027 个字节左右约 40 次,有时(非常罕见)一个或多个字节丢失。

让我感到困惑的是,实际字节并没有“丢失”,它只是设置为 0,而与原始数据无关。(顺便说一下,我正在使用 TCP)

这是发送代码:

    public void Send(byte[] data)
    {
        if (!server)
        {
            if (CheckConnection(serv))
            {
                serv.Send(BitConverter.GetBytes(data.Length));
                serv.Receive(new byte[1]);
                serv.Send(data);
                serv.Receive(new byte[1]);
            }
        }
    }

和接收代码:

    public byte[] Receive()
    {
        if (!server)
        {
            if (CheckConnection(serv))
            {
                byte[] TMP = new byte[4];
                serv.Receive(TMP);
                TMP = new byte[BitConverter.ToInt32(TMP, 0)];
                serv.Send(new byte[1]);
                serv.Receive(TMP);
                serv.Send(new byte[1]);
                return TMP;
            }
            else return null;
        }
        else return null;
    }

空字节的发送和接收只是为了使系统保持同步。我个人认为问题出在系统的接收端。虽然无法证明那架喷气式飞机。

4

1 回答 1

5

仅仅因为您提供Receive(TMP)一个 4 字节数组并不意味着它将用 4 个字节填充该数组。接收调用允许在数组中放入1TMP.Length字节之间的任何位置。您必须检查返回int的数组以查看填充了多少字节。

网络连接是基于流的,而不是基于消息的。您放在线路上的任何字节都会连接到一个大队列中,并在另一端可用时读取。因此,如果您发送了两个数组1,1,1,1并且2,2,2,2完全有可能在接收端您Receive使用 4 字节数组调用 3 次并得到

  • 1,1,0,0(收到退回2
  • 1,1,2,2(收到退回4
  • 2,2,0,0(收到退回2

所以你需要做的是查看你返回的值Receive并继续循环直到你的字节数组已满。

byte[] TMP = new byte[4];

//loop till all 4 bytes are read
int offset = 0;
while(offset < TMP.Length)
{
    offset += serv.Receive(TMP, offset, TMP.Length - offset, SocketFlags.None);
}
TMP = new byte[BitConverter.ToInt32(TMP, 0)];

//I don't understand why you are doing this, it is not necessary.
serv.Send(new byte[1]); 

//Reset the offset then loop till TMP.Length bytes are read.
offset = 0;
while(offset < TMP.Length)
{
    offset += serv.Receive(TMP, offset, TMP.Length - offset, SocketFlags.None);
}

//I don't understand why you are doing this, it is not necessary.
serv.Send(new byte[1]);

return TMP;

最后你说“网络流让你感到困惑”,我敢打赌上述问题是让你感到困惑的事情之一,再往下走不会消除那些复杂性。如果您希望这些复杂的部分消失,因此您不必处理它们,您将需要使用第三方库,它将在库内为您处理它。

于 2013-11-15T22:26:03.063 回答