packet structure

main
syneffort 2 years ago
parent ac15e63a0a
commit bf645548c5
  1. 13
      MySolution/STcpHelper/Packet/ISTcpPacket.cs
  2. 14
      MySolution/STcpHelper/Packet/PacketType.cs
  3. 27
      MySolution/STcpHelper/Packet/SBufferHelper.cs
  4. 42
      MySolution/STcpHelper/Packet/STcpPacketHeader.cs
  5. 40
      MySolution/STcpHelper/Packet/STcpTextPacket.cs
  6. 44
      MySolution/STcpHelper/STcpClient.cs
  7. 2
      MySolution/STcpHelper/STcpHelper.csproj
  8. 48
      MySolution/STcpHelper/STcpServer.cs
  9. 2
      MySolution/SerialComApp/SerialCommApp.resx

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STcpHelper.Packet
{
public interface ISTcpPacket
{
byte[] Serialize();
}
}

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STcpHelper.Packet
{
public enum PacketType
{
TEXT = 0,
}
}

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STcpHelper.Packet
{
static class SBufferHelper
{
public static byte[] GetBuffer(int size, params byte[][] args)
{
byte[] bytes = new byte[size];
int cursor = 0;
for (int i = 0; i < args.Length; i++)
{
byte[] data = args[i];
Array.Copy(data, 0, bytes, cursor, data.Length);
cursor += data.Length;
}
return bytes;
}
}
}

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace STcpHelper.Packet
{
/// <summary>
/// 4byte header
/// </summary>
public class STcpPacketHeader : ISTcpPacket
{
public PacketType Type { get; private set; }
public short DataLength { get; private set; }
public STcpPacketHeader(PacketType type, int dataLength)
{
Type = type;
DataLength = (short)dataLength;
}
public STcpPacketHeader(byte[] buffer)
{
int cursor = 0;
this.Type = (PacketType)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor));
cursor += 2;
this.DataLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor));
}
// [2bytes Type][2bytes Size]
public byte[] Serialize()
{
byte[] type = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)this.Type));
byte[] size = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(this.DataLength));
return SBufferHelper.GetBuffer(type.Length + size.Length, type, size);
}
}
}

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace STcpHelper.Packet
{
public class STcpTextPacket : ISTcpPacket
{
public string Text { get; private set; }
public STcpTextPacket(string text)
{
this.Text = text;
}
public STcpTextPacket(byte[] dataBuffer)
{
int cursor = 0;
short textSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(dataBuffer, cursor));
cursor += sizeof(short);
this.Text = Encoding.UTF8.GetString(dataBuffer, cursor, textSize);
}
public byte[] Serialize()
{
byte[] text = Encoding.UTF8.GetBytes(Text);
byte[] textSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)text.Length));
// 4byte header
STcpPacketHeader header = new STcpPacketHeader(PacketType.TEXT, text.Length + textSize.Length);
// [2bytes text size][n bytes text]
return SBufferHelper.GetBuffer(4 + textSize.Length + text.Length, header.Serialize(), textSize, text);
}
}
}

@ -1,5 +1,7 @@
using System; using STcpHelper.Packet;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
@ -17,6 +19,9 @@ namespace STcpHelper
private TcpClient _client; private TcpClient _client;
private NetworkStream _stream; private NetworkStream _stream;
private readonly int HEADER_SIZE = 4;
private readonly int BUFFER_SIZE = 1024;
public async void Connect(string ip, int port) public async void Connect(string ip, int port)
{ {
try try
@ -28,20 +33,35 @@ namespace STcpHelper
_cts = new CancellationTokenSource(); _cts = new CancellationTokenSource();
_ = Task.Run(async () => _ = Task.Run(async () =>
{ {
byte[] readBuffer = new byte[1024]; byte[] headerBuffer = new byte[HEADER_SIZE];
byte[] dataBuffer = new byte[BUFFER_SIZE];
while (true) while (true)
{ {
Thread.Sleep(50); Thread.Sleep(50);
if (_cts.IsCancellationRequested) if (_cts.IsCancellationRequested)
break; break;
int bytesRead = await this._stream.ReadAsync(readBuffer); int headerBytesRead = await _stream.ReadAsync(headerBuffer, 0, HEADER_SIZE);
if (bytesRead < 1) if (headerBytesRead != 4)
break; {
WriteError(new Exception("Cannot read header"));
return;
}
STcpPacketHeader header = new STcpPacketHeader(headerBuffer);
short dataSize = header.DataLength;
int totalRecv = 0;
while (totalRecv < dataSize)
{
int dataBytesRead = await _stream.ReadAsync(dataBuffer, totalRecv, dataSize - totalRecv);
totalRecv += dataBytesRead;
}
string message = Encoding.UTF8.GetString(readBuffer, 0, bytesRead); if (header.Type == PacketType.TEXT)
if (this.MessageCallback != null) {
this.MessageCallback(this, message); STcpTextPacket packet = new STcpTextPacket(dataBuffer);
WriteMessage(packet.Text);
}
} }
}, _cts.Token); }, _cts.Token);
} }
@ -51,11 +71,17 @@ namespace STcpHelper
} }
} }
private byte[] MakeTextPacket(string text)
{
STcpTextPacket packet = new STcpTextPacket(text);
return packet.Serialize();
}
public async void SendMessage(string message) public async void SendMessage(string message)
{ {
try try
{ {
byte[] sendBytes = Encoding.UTF8.GetBytes(message); byte[] sendBytes = MakeTextPacket(message);
await _stream.WriteAsync(sendBytes); await _stream.WriteAsync(sendBytes);
} }
catch (Exception ex) catch (Exception ex)

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>

@ -1,4 +1,5 @@
using System.Net; using STcpHelper.Packet;
using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
@ -10,6 +11,7 @@ namespace STcpHelper
private List<TcpClient> _clients; private List<TcpClient> _clients;
private readonly int HEADER_SIZE = 4;
private readonly int BUFFER_SIZE; private readonly int BUFFER_SIZE;
private int _port; private int _port;
@ -47,17 +49,37 @@ namespace STcpHelper
{ {
using (NetworkStream stream = client.GetStream()) using (NetworkStream stream = client.GetStream())
{ {
byte[] buffer = new byte[BUFFER_SIZE]; byte[] headerBuffer = new byte[HEADER_SIZE];
int bytesRead; byte[] dataBuffer = new byte[BUFFER_SIZE];
try try
{ {
while ((bytesRead = await stream.ReadAsync(buffer, 0, BUFFER_SIZE)) > 0) while (true)
{ {
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead); int headerBytesRead = await stream.ReadAsync(headerBuffer, 0, HEADER_SIZE);
WriteMessage($"[{client.Client.RemoteEndPoint.ToString()}] {message}"); if (headerBytesRead != 4)
{
// Broadcast WriteError(new Exception("Cannot read header"));
BroadcastMessage(message, client); return;
}
STcpPacketHeader header = new STcpPacketHeader(headerBuffer);
short dataSize = header.DataLength;
int totalRecv = 0;
while (totalRecv < dataSize)
{
int dataBytesRead = await stream.ReadAsync(dataBuffer, totalRecv, dataSize - totalRecv);
totalRecv += dataBytesRead;
}
if (header.Type == PacketType.TEXT)
{
STcpTextPacket packet = new STcpTextPacket(dataBuffer);
WriteMessage($"[{client.Client.RemoteEndPoint.ToString()}] Type: {header.Type.ToString()}");
// Broadcast
BroadcastMessage(packet.Text, client);
}
if (!IsClientConnected(client)) if (!IsClientConnected(client))
break; break;
@ -81,9 +103,15 @@ namespace STcpHelper
_cts.Cancel(); _cts.Cancel();
} }
private byte[] MakeTextPacket(string text)
{
STcpTextPacket packet = new STcpTextPacket(text);
return packet.Serialize();
}
private void BroadcastMessage(string message, TcpClient sender) private void BroadcastMessage(string message, TcpClient sender)
{ {
byte[] resonseByte = Encoding.UTF8.GetBytes(message); byte[] resonseByte = MakeTextPacket(message);
foreach (TcpClient client in _clients) foreach (TcpClient client in _clients)
{ {
if (client != sender && IsClientConnected(client)) if (client != sender && IsClientConnected(client))

@ -121,7 +121,7 @@
<data name="portRefreshButton.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="portRefreshButton.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL
DwAACw8BkvkDpQAAAsBJREFUaEPt2cnLTXEcx/FrzJCphJ0F2diIbEQokWFnzhClyFB6yEJEyh+gUMaU DgAACw4BQL7hQQAAAsBJREFUaEPt2cnLTXEcx/FrzJCphJ0F2diIbEQokWFnzhClyFB6yEJEyh+gUMaU
WdlYWLBRiszjAmFjaUgZMvP+LE6dTp9z7jnnnt990PnUa/N07+/7u/ee3/g06tSpU+efzihswFncxzt8 WdlYWLBRiszjAmFjaUgZMvP+LE6dTp9z7jnnnt990PnUa/N07+/7u/ee3/g06tSpU+efzihswFncxzt8
x1e8xm0cx2oMx1+R7liOG/hdwC9cxXx0Q6dkNp7DdbCIh5iKtqUvjsF1piz9InvQE0EzDPfgOlGFKxiE x1e8xm0cx2oMx1+R7liOG/hdwC9cxXx0Q6dkNp7DdbCIh5iKtqUvjsF1piz9InvQE0EzDPfgOlGFKxiE
IBmKZ3CF03zBt8TfmrmFAag0fXAXrmCcXrMd4zAYUYZgInbjCdx74y6h0sF9BK5QRANxJvKkKxaj2QSw IBmKZ3CF03zBt8TfmrmFAag0fXAXrmCcXrMd4zAYUYZgInbjCdx74y6h0sF9BK5QRANxJvKkKxaj2QSw

Loading…
Cancel
Save