From ece0dffd8560e3dc817762937d3a2f78ee44973a Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 16 Dec 2021 16:41:29 +1000 Subject: [PATCH] Implementing Packet Framing Surrounding packets with Int32 6655 to identify packet structure --- Client.cs | 66 +++++++++++++++-------------- Managers/PacketManager.cs | 9 +++- Server.cs | 87 +++++++++++++++++++++++++++++++++++---- 3 files changed, 122 insertions(+), 40 deletions(-) diff --git a/Client.cs b/Client.cs index 2c875a3..0d348f8 100644 --- a/Client.cs +++ b/Client.cs @@ -73,63 +73,67 @@ namespace Articulate_Network await Task.Run(() => { byte[] buffer = new byte[bufferSize]; - int offset = 0; while (true) { int bytesToRead = tcp.Client.Receive(buffer, offset, buffer.Length - offset, SocketFlags.None); - //Console.WriteLine("Bytes to read: " + bytesToRead); + if (offset > 0) + offset = 0; - var ms = new MemoryStream(buffer, 0, bytesToRead); + var ms = new MemoryStream(buffer); var br = new BinaryReader(ms); while (ms.Position < ms.Length) { + if (ms.Position + 4 > ms.Length) + break; + + int magic = br.ReadInt32(); + + if (magic != 6655) + { + //Console.WriteLine("Not the start of a packet."); + continue; + } + int length = (int)br.ReadInt64(); - OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs() + if (ms.Position + length > ms.Length) // Received partial packet data, store partial data and continue { - Packet = Get().DeserializePacket(ms) - }); - - int end = (int)br.ReadInt64(); - - bool endOfPacket = end == length; - - if (endOfPacket && ms.Position < ms.Length) - { - int nextPacketSize = (int)br.ReadInt64(); - - ms.Position -= 8; - - Console.WriteLine("Next size: " + nextPacketSize); + ms.Position -= 12; offset = (int)(ms.Length - ms.Position); + //Console.WriteLine($"Partial data. Offset: {offset}"); + buffer = new byte[bufferSize]; ms.Read(buffer, 0, offset); - break; } - //Console.WriteLine(ms.Position); + ms.Position += length; - /*if (ms.Position + length > ms.Length) + int end = (int)br.ReadInt64(); + + ms.Position -= 8; + ms.Position -= length; + + if (length == end && length > 1) // Valid packet, trigger event { - Console.WriteLine("Bytes to read: " + bytesToRead); - Console.WriteLine("Memory length: " + ms.Length); - Console.WriteLine("Memory Pos: " + ms.Position); - Console.WriteLine("Length: " + length); - ms.Position -= 8; + var p = Get().DeserializePacket(ms); - buffer = new byte[bufferSize]; - - ms.Read(buffer, 0, offset); - break; - }*/ + OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs() + { + Packet = p + }); + } + else + { + Console.WriteLine($"Not a valid packet. Length: {length} - End: {end} - Offset: {offset} - Position: {ms.Position}"); + } } } }); diff --git a/Managers/PacketManager.cs b/Managers/PacketManager.cs index 3f69161..8845ebe 100644 --- a/Managers/PacketManager.cs +++ b/Managers/PacketManager.cs @@ -104,15 +104,18 @@ namespace Articulate_Network.Managers //Console.WriteLine(field.Name); } - long length = buffer.Length; byte[] packetData = buffer.ToArray(); + long length = packetData.Length; buffer.SetLength(0); + binaryWriter.Write(6655); binaryWriter.Write(length); binaryWriter.Write(packetData); binaryWriter.Write(length); + //Console.WriteLine("Sent bytes: " + length); + watch.Stop(); //Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds"); @@ -127,7 +130,7 @@ namespace Articulate_Network.Managers string typeName = reader.ReadString(); - Console.WriteLine(typeName); + //Console.WriteLine(typeName); Packet packet = packetInstances[typeName];/*(IPacket)Activator.CreateInstance(typeof(T));*/ @@ -160,6 +163,8 @@ namespace Articulate_Network.Managers } } + reader.ReadInt64(); + watch.Stop(); //Console.WriteLine($"Deserialize time: {watch.ElapsedTicks / 10} microseconds"); diff --git a/Server.cs b/Server.cs index 17309cc..30c8af4 100644 --- a/Server.cs +++ b/Server.cs @@ -61,7 +61,7 @@ namespace Articulate_Network if (clients[i] == null) { clients[i] = client; - Console.WriteLine($"Client {i+1} connected from {(client.Client.RemoteEndPoint as IPEndPoint).Address}."); + Console.WriteLine($"Client {i + 1} connected from {(client.Client.RemoteEndPoint as IPEndPoint).Address}."); break; } @@ -71,7 +71,7 @@ namespace Articulate_Network } } - public async Task ReceiveData(TcpClient client) + /*public async Task ReceiveData(TcpClient client) { await Task.Run(() => { @@ -102,13 +102,83 @@ namespace Articulate_Network } catch (SocketException e) { - for (int i = 0; i < clients.Length; i++) - if (clients[i] == client) + + } + } + }); + + return false; + }*/ + + public async Task ReceiveData(TcpClient client) + { + await Task.Run(() => + { + byte[] buffer = new byte[16384]; + int offset = 0; + + while (client.Connected) + { + try + { + int bytesToRead = client.Client.Receive(buffer, offset, buffer.Length - offset, SocketFlags.None); + + if (bytesToRead == 0) + { + Console.WriteLine("No data."); + continue; + } + + var ms = new MemoryStream(buffer); + var br = new BinaryReader(ms); + + if (offset > 0) + offset = 0; + + while (ms.Position < ms.Length) + { + br.ReadInt32(); + int length = (int)br.ReadInt64(); + if (length < 0) + break; + + if (ms.Position + length > ms.Length) { - clients[i] = null; - Console.WriteLine($"Client {i+1} lost connection."); + ms.Position -= 8; + + buffer = new byte[16384]; + + offset = (int)(ms.Length - ms.Position); + + ms.Read(buffer, 0, offset); + break; } + ms.Position += length; + + int end = (int)br.ReadInt64(); + + ms.Position -= 8; + + if (length == end && length < 1) + break; + + ms.Position -= length; + + var p = Get().DeserializePacket(ms); + + OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs() + { + Packet = p, + Client = client + }); + + br.ReadInt64(); + } + } + catch (SocketException e) + { + Console.WriteLine("Client disconnected."); } } }); @@ -122,7 +192,10 @@ namespace Articulate_Network { byte[] buffer = Get().SerializePacket(packet); - tcpClient.Client.Send(buffer, buffer.Length, SocketFlags.None); + int sentBytes = tcpClient.Client.Send(buffer, buffer.Length, SocketFlags.None); + + if (sentBytes == 0) + Console.WriteLine($"Sent: {sentBytes}"); }); return false;