Skip to content

Instantly share code, notes, and snippets.

@Jeevananthan-23
Last active January 10, 2024 14:21
Multithread TCP Sever & HTTPClient written in C#(Managed Code)
using System.Buffers;
string serverUrl = "http://localhost:2305";
int numRequests = 100000;
int concurrency = 100;
using HttpClient client = new();
using var semaphore = new SemaphoreSlim(concurrency);
var tasks = new Task[numRequests];
for (int i = 0; i < numRequests; i++)
tasks[i] = SendRequestAsync(client, serverUrl, semaphore);
await Task.WhenAll(tasks);
static async Task SendRequestAsync(HttpClient client, string url, SemaphoreSlim semaphore)
{
// Use MemoryPool<byte> to rent a buffer
using var memoryPool = MemoryPool<byte>.Shared;
var rentMemory = memoryPool.Rent(1024).Memory;
await semaphore.WaitAsync();
try
{
var watch = System.Diagnostics.Stopwatch.StartNew();
using HttpResponseMessage response = await client.GetAsync(url);
using var stream = await response.Content.ReadAsStreamAsync();
var endofstrem = await stream.ReadAsync(rentMemory);
var servermsg = System.Text.Encoding.UTF8.GetString(rentMemory.Span[..endofstrem]);
watch.Stop();
Console.WriteLine($"Status Code: {response.StatusCode}, Message response: {servermsg} Duration: {watch.ElapsedMilliseconds} ms");
}
finally
{
semaphore.Release();
}
}
using System.Buffers;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Channels;
var ipEndPoint = new IPEndPoint(IPAddress.Any, 2305);
using TcpListener listener = new(ipEndPoint);
var channel = Channel.CreateBounded<TcpClient>(100);
try
{
//listern with backlog (pending connection)
listener.Start();
Console.WriteLine("Server is listening on port 2305...");
while (true)
{
Console.WriteLine("Waiting for a client to connect...");
TcpClient handler = await listener.AcceptTcpClientAsync().ConfigureAwait(true);
Console.WriteLine("Client connected.");
await channel.Writer.WriteAsync(handler);
// handle multiple requests
_ = HandleRequestAsync(channel.Reader);
}
}
finally
{
listener.Stop();
}
static async Task HandleRequestAsync(ChannelReader<TcpClient> channel)
{
// Use MemoryPool<byte> to rent a buffer
using var memoryPool = MemoryPool<byte>.Shared;
var rentMemory = memoryPool.Rent(1024).Memory;
await foreach (var handler in channel.ReadAllAsync())
{
Stopwatch sw = Stopwatch.StartNew();
using NetworkStream stream = handler.GetStream();
var remoteEndPoint = handler.Client.RemoteEndPoint;
int bytesRead = await stream.ReadAsync(rentMemory);
Encoding.UTF8.GetString(rentMemory.Span[..bytesRead]);
Console.WriteLine($"Received from client port {remoteEndPoint}");
Console.WriteLine("Processing the request..");
await Task.Delay(5000);
var clientMessage = $"HTTP/1.1 200 OK\r\n\r\nHello, World! 📅 {DateTime.Now} 🕛\r\n".AsMemory();
var sendMessaggeBytes = Encoding.UTF8.GetBytes(clientMessage.Span, rentMemory.Span);
await stream.WriteAsync(rentMemory[..clientMessage.Length]);
Console.WriteLine($"Sent message.{Encoding.UTF8.GetString(rentMemory.Span[..clientMessage.Length])}");
handler.Close();
sw.Stop();
Console.WriteLine($"Connection handled time: {sw.ElapsedMilliseconds} ms");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment