我目前有一个非常奇怪的问题,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;
}
}