Morning, I’ve a TCP Server and a TCP Client.
Here’s the code of the server:
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;
}
}
And here’s the code of the client:
[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;
}
}
}
But when I’m sending a packet from the server to the client (handshake) the client get’s an exception in the “ArrayToPacket” function at “packet = (Packet) formatter.Deserialize(stream);”
The exact message is: The assembly “ComDee, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” could’nt be found.
(ComDee is the assembly where the server runs).
Why? The packet-structure of the client is the same as the structrue of the server.
UPDATE
I’ve edited the Server and Client class and used protobuf-net.
But the “OnReceive” in the Client-Class doesn’t get called.
Where is the problem?
Server-Class:
[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;
}
}
And here is the Client-Class:
[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;
}
}
}
Types are scoped by their assembly, and BinaryFormatter serializes the type metadata (the assembly-qualified name, etc). Having a copy of the same
classin two places is not enough: they are not the same type unless they came from the same assembly.Also note that
BinaryFormatteris pretty verbose in what it stores on the wire. If you want something that addresses both of these issues without you needing to do all the serialization manually, then protobuf-net will help:For example:
and use
Serializer.Serializeinstead ofBinaryFormatter.