gpt4 book ai didi

c# - 通过网络发送自定义结构 - SerializationException

转载 作者:可可西里 更新时间:2023-11-01 02:39:53 28 4
gpt4 key购买 nike

早上好,我有一个 TCP 服务器和一个 TCP 客户端。这是服务器的代码:

public static class Server
{
private static IPEndPoint endPoint;

private static TcpListener tcpServer;
private static List<Client> clients;
private static Thread threadListen;

private static ASCIIEncoding encoding;

public static void Initialize(IPAddress allowedIPAddress, int port)
{
endPoint = new IPEndPoint(allowedIPAddress, port);

tcpServer = new TcpListener(endPoint);
clients = new List<Client>();
threadListen = new Thread(new ThreadStart(Listen));

encoding = new ASCIIEncoding();
}

public static void Start()
{
threadListen.Start();
}

public static byte[] PacketToArray(Packet packet)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();

formatter.Serialize(stream, packet);
byte[] packetArray = stream.GetBuffer();

stream.Close();

return packetArray;
}

public static Packet ArrayToPacket(byte[] array)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(array);

Packet packet = new Packet();
packet = (Packet) formatter.Deserialize(stream);

stream.Close();

return packet;
}

public static void Send(Client target, Packet packet)
{
byte[] packetArray = PacketToArray(packet);

target.networkStream.Write(packetArray, 0, packetArray.Length);
target.networkStream.Flush();
OnSend(packet);
}

private static void Listen()
{
tcpServer.Start();

while (true)
{
try
{
Client client = new Client();
client.tcpClient = tcpServer.AcceptTcpClient();
client.networkStream = client.tcpClient.GetStream();
client.thread = new Thread(new ParameterizedThreadStart(HandleCommunication));

clients.Add(client);
client.thread.Start(client);
OnJoin(client);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
break;
}
}
}

private static void HandleCommunication(object client)
{
Client handleClient = (Client) client;

byte[] messageBuffer = new byte[4096];
int bytesRead = 0;

while (true)
{
bytesRead = 0;

try
{
bytesRead = handleClient.networkStream.Read(messageBuffer, 0, messageBuffer.Length);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
break;
}

if (bytesRead == 0)
{
clients.Remove(handleClient);
OnLeave(handleClient);
break;
}

Packet packet = ArrayToPacket(messageBuffer);
OnReceive(packet);
}
}

private static void OnStart()
{
Console.WriteLine("Server started on port .");
}

private static void OnJoin(Client client)
{
Console.WriteLine("Client [ID] connected.");

Send(client, PacketGenerator.Generate(OpCodes.opHandshake, null));
}

private static void OnLeave(Client client)
{
Console.WriteLine("Client [ID] disconnected.");
}

private static void OnSend(Packet packet)
{
Console.WriteLine("Server: " + packet.opcode.ToString() + " | " + packet.message);
}

private static void OnReceive(Packet packet)
{
Console.WriteLine("Client [ID]: " + packet.opcode.ToString() + " | " + packet.message);
}

public struct Client
{

public TcpClient tcpClient;
public NetworkStream networkStream;
public Thread thread;

}

}

这是客户端的代码:

[Serializable]
public struct Packet
{

public int opcode;
public string message;

}

public static class Client
{

private static IPEndPoint endPoint;

private static TcpClient tcpClient;
private static NetworkStream networkStream;
private static Thread threadCommunication;

private static ASCIIEncoding encoding;

public static void Initialize(string ipAddress, int port)
{
endPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
tcpClient = new TcpClient();
networkStream = null;
threadCommunication = new Thread(new ThreadStart(HandleCommunication));

encoding = new ASCIIEncoding();
}

public static void Connect()
{
tcpClient.Connect(endPoint);
threadCommunication.Start();
Console.WriteLine("Connected to server.");

networkStream = tcpClient.GetStream();
}

public static byte[] PacketToArray(Packet packet)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();

formatter.Serialize(stream, packet);
byte[] packetArray = stream.GetBuffer();

stream.Close();

return packetArray;
}

public static Packet ArrayToPacket(byte[] array)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(array);

Packet packet = new Packet();
packet = (Packet)formatter.Deserialize(stream);

stream.Close();

return packet;
}

public static void Send(Packet packet)
{
byte[] packetArray = PacketToArray(packet);

networkStream.Write(packetArray, 0, packetArray.Length);
networkStream.Flush();
OnSend(packet);
}

private static void HandleCommunication()
{
byte[] messageBuffer = new byte[4096];
int bytesRead = 0;

while (true)
{
bytesRead = 0;

try
{
bytesRead = networkStream.Read(messageBuffer, 0, messageBuffer.Length);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
break;
}

if (bytesRead == 0)
{
Console.WriteLine("Connection closed.");
break;
}

Packet packet = ArrayToPacket(messageBuffer);
OnReceive(packet);
}
}

private static void OnSend(Packet packet)
{
Console.WriteLine("Client [ID]: " + packet.opcode.ToString() + " | " + packet.message);
}

private static void OnReceive(Packet packet)
{
Console.WriteLine("Server: " + packet.opcode.ToString() + " | " + packet.message);

switch (packet.opcode)
{

case OpCodes.opHandshake:
Send(PacketGenerator.Generate(OpCodes.opHandshake, null));
break;

}
}

}

但是当我从服务器向客户端发送数据包(握手)时,客户端在“packet = (Packet) formatter.Deserialize(stream);”处的“ArrayToPacket”函数中出现异常。确切的消息是:找不到程序集“ComDee,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”。(ComDee 是运行服务器的程序集)。

为什么?客户端的包结构与服务端的结构相同。

更新

我编辑了服务器和客户端类并使用了 protobuf-net。但是客户端类中的“OnReceive”不会被调用。问题出在哪里?服务器类:

[ProtoContract]
public struct Packet
{

[ProtoMember(1)] public int opcode;
[ProtoMember(2)] public string message;

}

public static class Server
{

private static IPEndPoint endPoint;

private static TcpListener tcpServer;
private static List<Client> clients;
private static Thread threadListen;

private static ASCIIEncoding encoding;

public static void Initialize(IPAddress allowedIPAddress, int port)
{
endPoint = new IPEndPoint(allowedIPAddress, port);

tcpServer = new TcpListener(endPoint);
clients = new List<Client>();
threadListen = new Thread(new ThreadStart(Listen));

encoding = new ASCIIEncoding();
}

public static void Start()
{
threadListen.Start();
}

public static byte[] PacketToArray(Packet packet)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();

Serializer.Serialize<Packet>(stream, packet);
byte[] packetArray = stream.GetBuffer();

stream.Close();

return packetArray;
}

public static Packet ArrayToPacket(byte[] array)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(array);

Packet packet = new Packet();
packet = Serializer.Deserialize<Packet>(stream);

stream.Close();

return packet;
}

public static void Send(Client target, Packet packet)
{
byte[] packetArray = PacketToArray(packet);

target.networkStream.Write(packetArray, 0, packetArray.Length);
target.networkStream.Flush();
OnSend(packet);
}

private static void Listen()
{
tcpServer.Start();
OnStart();

while (true)
{
try
{
Client client = new Client();
client.tcpClient = tcpServer.AcceptTcpClient();
client.networkStream = client.tcpClient.GetStream();
client.thread = new Thread(new ParameterizedThreadStart(HandleCommunication));

clients.Add(client);
client.thread.Start(client);
OnJoin(client);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
break;
}
}
}

private static void HandleCommunication(object client)
{
Client handleClient = (Client) client;

byte[] messageBuffer = new byte[4096];
int bytesRead = 0;

while (true)
{
bytesRead = 0;

try
{
bytesRead = handleClient.networkStream.Read(messageBuffer, 0, messageBuffer.Length);
}
catch
{
clients.Remove(handleClient);
OnLeave(handleClient);
break;
}

if (bytesRead == 0)
{
Packet packet = ArrayToPacket(messageBuffer);
OnReceive(packet);
}
}
}

private static void OnStart()
{
Console.WriteLine("Server started.");
}

private static void OnJoin(Client client)
{
Console.WriteLine("Client [ID] connected.");

Send(client, PacketGenerator.Generate(OpCodes.opHandshake, null));
}

private static void OnLeave(Client client)
{
Console.WriteLine("Client [ID] disconnected.");
}

private static void OnSend(Packet packet)
{
Console.WriteLine("Server: " + packet.opcode.ToString() + " | " + packet.message);
}

private static void OnReceive(Packet packet)
{
Console.WriteLine("Client [ID]: " + packet.opcode.ToString() + " | " + packet.message);
}

public struct Client
{

public TcpClient tcpClient;
public NetworkStream networkStream;
public Thread thread;

}

}

这是客户端类:

[ProtoContract]
public struct Packet
{

[ProtoMember(1)]
public int opcode;
[ProtoMember(2)]
public string message;

}

public static class Client
{

private static IPEndPoint endPoint;

private static TcpClient tcpClient;
private static NetworkStream networkStream;
private static Thread threadCommunication;

private static ASCIIEncoding encoding;

public static void Initialize(string ipAddress, int port)
{
endPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
tcpClient = new TcpClient();
networkStream = null;
threadCommunication = new Thread(new ThreadStart(HandleCommunication));

encoding = new ASCIIEncoding();
}

public static void Connect()
{
tcpClient.Connect(endPoint);
threadCommunication.Start();
Console.WriteLine("Connected to server.");

networkStream = tcpClient.GetStream();
}

public static byte[] PacketToArray(Packet packet)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();

Serializer.Serialize<Packet>(stream, packet);
byte[] packetArray = stream.GetBuffer();

stream.Close();

return packetArray;
}

public static Packet ArrayToPacket(byte[] array)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(array);

Packet packet = new Packet();
packet = Serializer.Deserialize<Packet>(stream);

stream.Close();

return packet;
}

public static void Send(Packet packet)
{
byte[] packetArray = PacketToArray(packet);

networkStream.Write(packetArray, 0, packetArray.Length);
networkStream.Flush();
OnSend(packet);
}

private static void HandleCommunication()
{
byte[] messageBuffer = new byte[4096];
int bytesRead = 0;

while (true)
{
bytesRead = 0;

try
{
bytesRead = networkStream.Read(messageBuffer, 0, messageBuffer.Length);
}
catch
{
Console.WriteLine("Connection closed.");
break;
}

if (bytesRead == 0)
{
Packet packet = ArrayToPacket(messageBuffer);
OnReceive(packet);
}
}
}

private static void OnSend(Packet packet)
{
Console.WriteLine("Client [ID]: " + packet.opcode.ToString() + " | " + packet.message);
}

private static void OnReceive(Packet packet)
{
Console.WriteLine("Server: " + packet.opcode.ToString() + " | " + packet.message);

switch (packet.opcode)
{

case OpCodes.opHandshake:
Send(PacketGenerator.Generate(OpCodes.opHandshake, null));
break;

}
}

}

最佳答案

类型由它们的程序集限定范围,BinaryFormatter 序列化类型元数据(程序集限定名称等)。在两个地方拥有相同的副本是不够的:它们不是相同的类型,除非它们来自相同的程序集

另请注意,BinaryFormatter 在线路上存储的内容非常冗长。如果您想要解决这两个问题而无需手动执行所有序列化,那么 protobuf-net 将有所帮助:

  • 在电线上很密
  • 它不绑定(bind)特定类型;只要 A 和 B 看起来相似,就可以用 A 序列化并用 B 反序列化

例如:

[ProtoContract]
public struct Packet {
[ProtoMember(1)] public int opcode;
[ProtoMember(2)] public string message;
}

并使用 Serializer.Serialize 而不是 BinaryFormatter

关于c# - 通过网络发送自定义结构 - SerializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14727791/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com