C##BinaryFormatter的奇怪问题序列化/反序列化

时间:2017-04-24 16:39:06

标签: c# binaryformatter

我目前有一个非常奇怪的问题,BinaryFormatter序列化/反序列化我希望我能得到一些帮助。

目前,我目前正致力于在过去的两个月里使用Unity 5.5学习游戏开发。我决定挑战自己并创建一个多人游戏,我自己创建了网络部分。

大约一个星期前,我和一位朋友通过互联网对它进行了测试,所有这些都按预期工作,但昨天我发现了一个让它无法播放的问题。

[Serializable]
public class Packet
{
    //Remeber to change Packet function if changing something here
    public List<string> Gdata;
    public int PacketInt;
    public bool PacketBool;
    public string senderID;
    public PacketType packetType;

    public Packet(PacketType type, string senderID)
    {
        Gdata = new List<string>();
        this.senderID = senderID;
        this.packetType = type;
    }

    public Packet(byte[] packetBytes)
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream(packetBytes);

        Console.WriteLine(packetBytes);

        Packet p = (Packet)bf.Deserialize(ms);
        ms.Close();
        this.Gdata = p.Gdata;
        this.PacketInt = p.PacketInt;
        this.PacketBool = p.PacketBool;
        this.senderID = p.senderID;
        this.packetType = p.packetType;
    }

    public byte[] ToBytes()
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();

        bf.Serialize(ms, this);

        byte[] bytes = ms.ToArray();
        ms.Close();
        return bytes;
    }

    public static string GetIP4Address()
    {
        IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());

        foreach (IPAddress i in ips)
        {
            if (i.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                return i.ToString();
        }

        return "127.0.0.1";
    }
}

public enum PacketType
{
    /* Connection */
    Connecting,
    Handshake,
    ConnectionComfirmed,
    DataRequest,
    NewClient, // Sent from the server to all players online when a new player has connected, containing revelant data to sync the new player.
    Disconnecting,

    /* Errors */
    ServerError,

    /* Updates */
    Movement,
    PositionUpdate,

    /* Chat */
    Chat
}

我在下面描述的问题发生在 数据包p =(数据包)bf.Deserialize(ms);

这就是我用来处理数据包的方法。它已经附加到服务器软件和我正在创建的游戏的DLL中。它的工作原理如下:

void DataManager(Packet p)
{
    switch (p.packetType)
    {
        case PacketType.Connecting:
            if (p.Gdata[1] == ServerHandshake)
            {
                _clientID = p.senderID;

                Packet sp = new Packet(PacketType.Handshake, _clientID);
                sp.Gdata.Add(ClientHandshake);
                _socket.Send(sp.ToBytes());
            }
            break;
    }
}

在本地测试时,它的工作没有问题,并且在过去的2个月里一直运行良好。另外,正如我上面所写,我在一周前测试了一下,没有遇到任何问题。

然而,问题现在是由于某种原因,在同一时刻,我得到错误&#39;输入流不是有效的二进制格式&#39;每当通过互联网连接的人正在移动时。该部分的代码如下:

if (movement_vector != Vector2.zero)
        {
            anim.SetBool("iswalking", true);
            anim.SetFloat("input_x", movement_vector.x);
            anim.SetFloat("input_y", movement_vector.y);

            Packet p = new Packet(PacketType.Movement, GetComponent<Script_PlayerData>().Player_GUID);
            p.Gdata.Add(movement_vector.x.ToString());
            p.Gdata.Add(movement_vector.y.ToString());
            p.Gdata.Add(player.position.x.ToString());
            p.Gdata.Add(player.position.y.ToString());
            GameObject.Find("GameScripts").GetComponent<Script_Network>()._socket.Send(p.ToBytes());
            if (HasMoved == 0) HasMoved = 1;
        }

在执行此部分之前,服务器和游戏客户端来回发送几个数据包,这样做完全正常。即使我添加到游戏中的聊天工作也按预期工作,但只要通过互联网连接的播放器移动到任何方向,我就会得到 &#39;输入流不是抛出有效的二进制格式&#39; 异常,即使它在本地工作正常,最多可连接10个客户端。

我一直在互联网上四处寻找解决这个问题的方法,但到目前为止我没有测试或阅读的任何内容一直在为我工作。

自从我第一次连接远程播放器进行测试以来,我根本没有修改过这段代码。我每次编译DLL后都会更新Unity项目中的DLL。

作为最后的手段,我在这里问。任何人都知道什么可能使它表现得像这样,并且有人知道它的解决方案吗?

编辑:显然忘了指定它的TCP。下面的代码片段可能有助于您更好地了解它的工作原理:

服务器程序:

    void SetupSocket()
    {
        ConsoleMessage("Initializing socket...");
        _listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


        IPEndPoint ip = new IPEndPoint(IPAddress.Parse(s_config.ServerIP), s_config.ServerPort);

        ConsoleMessage("Binding server to " + s_config.ServerIP + ":" + s_config.ServerPort);

        _listenerSocket.Bind(ip);
        _listenerThread = new Thread(ListenThread);
        _listenerThread.Start();
    }

    void NetworkListener(Socket _socket, string GUID) // Threaded for each client connected
    {
        OnlinePlayers++;

        byte[] Buffer;
        int readBytes;
        try
        {

            for (;;)
            {
                int l = GetPlayerIndexSlot(GUID);
                if (l == -1) break;

                Buffer = new byte[_socket.SendBufferSize];

                readBytes = _socket.Receive(Buffer);

                if (readBytes > 0)
                {
                    Packet packet = new Packet(Buffer);
                    DataManager(_socket, packet);
                }
            }
        }
        catch (SocketException ex)
        {
            ConsoleMessage("Socket error: " + ex.ErrorCode + ", Client id: " + GUID);
            if (ex.ErrorCode == 10054) // WSAECONNRESET - Connection reset by peer
            {
                OnPlayerDisconnecting(_socket, 5);
            }
        }
    }

    void DataManager(Socket _socket, Packet p)
    {
        switch (p.packetType)
        {
            case PacketType.Connecting:     ConnectingPacket(_socket, p.Gdata[0]);                                                  break;
            case PacketType.Handshake:      HandshakeProcess(p.senderID, _socket, p.Gdata[0]);                                      break;
            case PacketType.Disconnecting:  OnPlayerDisconnecting(_socket, 0);                                                      break;
            case PacketType.DataRequest:    DataRequest(p.Gdata[0], _socket, p.senderID);                                           break;
            case PacketType.Movement:       PlayerMovement(p.senderID, _socket, p.Gdata[0], p.Gdata[1], p.Gdata[2], p.Gdata[3]);    break;
            case PacketType.PositionUpdate: PlayerPositionUpdate(p.senderID, _socket, p.Gdata[0], p.Gdata[1]);                      break;
            case PacketType.Chat:           ChatMessage(p.senderID, _socket, p.Gdata[0]);                                           break;
        }
    }

0 个答案:

没有答案