-
Notifications
You must be signed in to change notification settings - Fork 4
1.AsyncTcpClient ‐ Server
- Utilizes SocketAsyncEventArgs to send and receive bytes without data manipulation.
- An asynchronous TCP client/server model that efficiently handles byte data transmission.
- Optimized for high-traffic scenarios involving small messages, where messages are concatenated and sent in batches under load.
- Capable of handling large file transfers, though it is recommended to chunk files rather than sending them in a single operation.
- Implements memory pooling to significantly reduce GC pressure.
- Optimized for environments with a high frequency of connection and disconnection events.
To initialise server and you can simply:
AsyncTcpServer server = new AsyncTcpServer(port:20008);
server.OnClientAccepted += HandleAccept;
server.OnClientDisconnected += HandleDisconnect;
server.OnBytesReceived += ServerBytesReceived;
server.StartServer();
AsyncTpcClient client = new AsyncTpcClient();
client.OnDisconnected += HandleDC;
client.OnBytesReceived += ClientBytesReceived;
client.Connect("127.0.0.1", 20008);
To send data with client:
byte[] data = new byte[10000];
client.SendAsync(data);
client.SendAsync(data, offset:200, count:50);
To send data with server:
Guid ClientId;
server.SendAsync(ClientId, data);
server.SendAsync(ClientId, data, offset:200, count:50);
Where client id comes from on accepted callback.
Sends never block the caller(until max buffered memory limit is reached). If send operation detects the underlying socket is busy with previous send, it will queue/buffer the messages. Once the send operation is complete socket will check the state of message buffer. if buffer is not empty it will loop for another send. Note that this operation sends entire buffer in bulk, not a single message. This provides great efficiency on small high traffic messages.
Receive is an async callback from socket. To keep message consistency, Receive wont be looped until your OnBytesReceived callback returns.
Remember that the buffer you receive on your callback is sockets buffer region, It will be owerwritten on next receive.
If you want to store this bytes, you must do a copy or it will be overwritten on next receive.
if you want to limit your max memory you can change:
server.MaxIndexedMemoryPerClient;
client.MaxIndexedMemory;
which will block the traffic once the threshold is reached, until buffered bytes are cleared.
There is an important configuration you should take into account Which you must set before starting the server:
client.GatherConfig = ScatterGatherConfig.UseQueue;
server.GatherConfig = ScatterGatherConfig.UseBuffer;
Determines whether to use queue or buffer for message gathering mechanism.
UseQueue requires your byte[] sources to be not modified after send.
Queue copies the data during the send operation from the array reference.
Hence, your data may be copied asynchronously.
UseBuffer will copy your data into a buffer on caller thread immediately. During socket send, a buffer swap will be performed(WriteBuffer and SendBuffer).
This means you can modify or reuse your data safely.
Queue implementation is more efficient and maybe suitable static resources or for short lived disposable data i.e.(Encoding.UTF8.GetBytes(string)).
Buffer provides data safety where your send byte[] or segment can be reused for manipulation, i.e. Streams.
All examples cam be found on Examples.
AsyncTcpServer server = new AsyncTcpServer(20008);
server.OnBytesReceived += ServerBytesReceived;
server.StartServer();
AsyncTpcClient client = new AsyncTpcClient();
client.OnBytesReceived += ClientBytesReceived;
client.Connect("127.0.0.1", 20008);
client.SendAsync(Encoding.UTF8.GetBytes("Hello I'm a client!"));
void ServerBytesReceived(Guid clientId, byte[] bytes, int offset, int count)
{
Console.WriteLine(Encoding.UTF8.GetString(bytes, offset, count));
server.SendBytesToClient(clientId, Encoding.UTF8.GetBytes("Hello I'm the server"));
}
void ClientBytesReceived(byte[] bytes, int offset, int count)
{
Console.WriteLine(Encoding.UTF8.GetString(bytes, offset, count));
}