早上,我有一个TCP服务器和一个TCP客户端。 这里是服务器的代码:通过网络发送自定义结构 - SerializationException
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是服务器运行的程序集)。
为什么?客户端的数据包结构与服务器的结构相同。
UPDATE
我编辑的服务器和客户端类,并使用protobuf网。 但客户端类中的“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;
}
}
}
您的读者在调用'ArrayToPacket'之前需要一直读取,直到它获得一个零或错误。否则,你试图解析整个消息的片段。 –
对不起,我在tcp编程方面比较新。 如何检查阅读是否完整? – namespace
您的发送逻辑似乎是“我编码消息,发送消息,然后关闭连接”。如果是这样,匹配的接收逻辑是“我一直在接收,直到连接关闭,然后我将收到的所有内容解析为单个消息”。但是您的收到代码不会这样做。请参阅[这个答案](http://stackoverflow.com/a/14715497/721269)来学习更大,更重要的课程。 –