早上,我有一个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是服务器运行的程序集。)
为什么呢?客户端的数据包结构与服务器的结构相同。
更新
我编辑了Server和Client类并使用了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;
}
}
}
答案 0 :(得分:3)
类型由其程序集确定范围,BinaryFormatter序列化类型元数据(程序集限定名称等)。在两个地方拥有相同class
的副本是不够的:它们不是相同的类型,除非它们来自相同的程序集。
另请注意,BinaryFormatter
在线上存储的内容非常详细。如果您想要解决这两个问题而无需手动完成所有序列化,那么protobuf-net将有所帮助:
例如:
[ProtoContract]
public struct Packet {
[ProtoMember(1)] public int opcode;
[ProtoMember(2)] public string message;
}
并使用Serializer.Serialize
代替BinaryFormatter
。