TcpClient接收未发送的字节?

时间:2017-03-29 12:31:39

标签: c# sockets serialization tcpclient tcplistener

我正在编写一个使用TcpListener作为服务器的程序。多个客户端连接到它并发送/接收数据包。

这些Packets只是包含数据的序列化自定义类。我使用BinaryFormatter来序列化和反序列化数据包:

[Serializable]
public class Packet
{
    public static implicit operator byte[](Packet p)
    {
        using (var memoryStream = new MemoryStream())
        {
            new BinaryFormatter().Serialize(memoryStream, p);
            return memoryStream.ToArray();
        }
    }

    protected byte[] Serialize(object o)
    {
        using (var memoryStream = new MemoryStream())
        {
            new BinaryFormatter().Serialize(memoryStream, o);
            return memoryStream.ToArray();
        }
    }

    public static object Deserialize(byte[] data)
    {
        using (var memoryStream = new MemoryStream(data))
            return new BinaryFormatter().Deserialize(memoryStream);
    }
}

以下是我发送的数据包示例:

[Serializable]
    public class Message : Packet
    {
        public string Text { get; set; }
        public Message(string text)
        {
            Text = text;
        }
        public byte[] Serialize()
        {
            return Serialize(this);
        }
    }

现在我发送此数据的方式是首先创建一个Header,它指定我们要序列化的数据包的长度,然后将该标头发送到NetworkStream,然后,它发送实际的数据包。

我为这样的任务写了一个扩展类:

public static class StreamExtension
{
    public static async Task WritePacket(this NetworkStream stream, byte[] packet)
    {
        var header = BitConverter.GetBytes(packet.Length); //Get packet length.
        await stream.WriteAsync(header, 0, header.Length); //Write packet length as header.
        await stream.WriteAsync(packet, 0, packet.Length); //Write actual packet.
        Console.WriteLine($"Writing packet with length {packet.Length}");
    }
}

现在,当我尝试连接时,它可以与第一个连接的客户端一起工作,它会发送和接收所有必要的数据包。但是当第二个客户端加入时,它最终会尝试反序列化甚至不发送的数据包。

我创建了一个try catch来查看问题是什么,我得到一个例外说:

  

二进制流'0'不包含有效的二进制头

这是在客户端接收数据的方法:

private async void ReceiveData()
        {
            var header = new byte[4]; //Indicator for how big our actual packet is.
            var stream = Server.GetStream();
            while (await stream.ReadAsync(header, 0, header.Length) != 0)
            {
                var packetLength = BitConverter.ToInt32(header, 0);
                var buffer = new byte[packetLength];
                await stream.ReadAsync(buffer, 0, buffer.Length); //Read packet.
                try {
                    var receivedPacket = Packet.Deserialize(buffer);
                    lbLog.Items.Add($"Received packet: {receivedPacket.GetType()}");
                    if (receivedPacket is SetPiece)
                    {
                        var setPiece = receivedPacket as SetPiece;
                        MyPiece = setPiece.Piece;
                        lblPiece.Text = $"You are {MyPiece}";
                    }
                    else if (receivedPacket is StartNew)
                    {
                        foreach (var box in Controls.OfType<PictureBox>())
                            box.Image = null;
                    }
                    else if (receivedPacket is SetTurn)
                    {
                        var setTurn = receivedPacket as SetTurn;
                        IsTurn = setTurn.IsMine;
                        lblTurn.Text = setTurn.IsMine ? "Your Turn" : $"{setTurn.Name}'s Turn";
                    }
                    else if (receivedPacket is Log)
                    {
                        var log = receivedPacket as Log;
                        lbLog.Items.Add(log.Message);
                    }
                }
                catch
                {
                    File.AppendAllLines("errors.txt", new[] { $"Error occurred with packet. Length of {buffer.Length}" });
                }
            }
        }

以下是服务器控制台的日志:

enter image description here

这是错误日志:

Error occurred with packet. Length of 162
Error occurred with packet. Length of 256
Error occurred with packet. Length of 1952797486

如果长度为1952797486的数据包从未发送过,我们怎么会出错呢?

关于我做错的任何想法?

0 个答案:

没有答案