Skip to content

Instantly share code, notes, and snippets.

@lucasteles
Last active September 20, 2023 19:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasteles/d2146950212c18da1e5d279b6581cd49 to your computer and use it in GitHub Desktop.
Save lucasteles/d2146950212c18da1e5d279b6581cd49 to your computer and use it in GitHub Desktop.
C# UDP Socket
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using static System.Text.Encoding;
using static System.Console;
const int MaxUdpByteSize = 65527;
static Socket CreateSocket(int port)
{
if (port is < IPEndPoint.MinPort or > IPEndPoint.MaxPort)
throw new ArgumentOutOfRangeException(nameof(port));
Socket socket = new(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
{
ExclusiveAddressUse = false,
Blocking = false,
};
IPEndPoint localEp = new(IPAddress.Any, port);
socket.Bind(localEp);
return socket;
}
static async ValueTask CreateServer(int port, CancellationToken ct = default)
{
using var socket = CreateSocket(port);
var buffer = GC.AllocateArray<byte>(length: MaxUdpByteSize, pinned: true).AsMemory();
var socketAddress = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort).Serialize();
WriteLine("Starting server");
while (!ct.IsCancellationRequested)
{
try
{
var receivedSize =
await socket.ReceiveFromAsync(buffer, SocketFlags.None, socketAddress, ct);
var receivedMsg = UTF8.GetString(buffer[..receivedSize].Span);
WriteLine(
$"Received {receivedSize} bytes from client {socketAddress}: {receivedMsg}");
var msgSize = UTF8.GetBytes($"ACK({receivedMsg.Length})", buffer.Span);
var sent = await socket
.SendToAsync(buffer[..msgSize], SocketFlags.None, socketAddress);
Debug.Assert(sent == msgSize);
}
catch (OperationCanceledException)
{
break;
}
}
}
static async ValueTask CreateClient(int port, int serverPort, CancellationToken ct = default)
{
using var socket = CreateSocket(port);
var buffer = GC.AllocateArray<byte>(length: MaxUdpByteSize, pinned: true).AsMemory();
var serverAddress = new IPEndPoint(IPAddress.Loopback, serverPort).Serialize();
await Task.Delay(1_000);
WriteLine("Starting client");
while (!ct.IsCancellationRequested)
{
try
{
WriteLine("Which msg?");
var msg = ReadLine() ?? string.Empty;
var bodySize = UTF8.GetBytes(msg, buffer.Span);
var sentSize = await socket
.SendToAsync(buffer[..bodySize], SocketFlags.None, serverAddress, ct);
Debug.Assert(sentSize == bodySize);
var responseSize = await socket
.ReceiveFromAsync(buffer, SocketFlags.None, serverAddress, ct);
var responseMsg = UTF8.GetString(buffer[..responseSize].Span);
WriteLine(
$"Received {responseSize} bytes from server {serverAddress}: {responseMsg}");
}
catch (OperationCanceledException)
{
break;
}
}
}
CancellationTokenSource cancellation = new();
CancelKeyPress += (_, args) =>
{
args.Cancel = true;
cancellation.Cancel();
};
const int serverPort = 9000;
const int clientPort = 9001;
var server = CreateServer(serverPort, cancellation.Token);
var client = CreateClient(clientPort, serverPort, cancellation.Token);
await Task.WhenAll(server.AsTask(), client.AsTask());
WriteLine("The End");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment