Skip to content

Instantly share code, notes, and snippets.

@lucasteles
Last active March 13, 2024 14:32
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/5bdd2e87eb4b85a10ba2ebc73ec08eef to your computer and use it in GitHub Desktop.
Save lucasteles/5bdd2e87eb4b85a10ba2ebc73ec08eef to your computer and use it in GitHub Desktop.
F# UDP Socket
open System.Net.Sockets
open System.Net
open System
open System.Text
open System.Threading
let localPort = 8800
let serverPort = 8888
let serverUri = Uri("http://localhost")
let log msg = printfn $"{DateTime.Now}: %A{msg}"
let socket =
new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
socket.Blocking <- false
socket.Bind(new IPEndPoint(IPAddress.Any, localPort))
let cts = new CancellationTokenSource()
let ct = cts.Token
let bufferSize = 1024
let stop () =
use _ = cts
use _ = socket
cts.CancelAsync() |> Async.AwaitTask |> Async.RunSynchronously
let receiver =
task {
let buffer = GC.AllocateArray<byte>(bufferSize, pinned = true)
let anyEndPoint = new IPEndPoint(IPAddress.Any, 0)
log "start receiveing..."
while not ct.IsCancellationRequested do
try
let! recv = socket.ReceiveFromAsync(buffer, anyEndPoint, ct)
log $"recv {Encoding.UTF8.GetString(buffer)} from {recv.RemoteEndPoint}"
with :? OperationCanceledException ->
log "stopping receiver..."
log "receiver stopped!"
}
let sender =
MailboxProcessor.Start(
(fun (inbox) ->
async {
let buffer = GC.AllocateArray<byte>(bufferSize, pinned = true)
let serverAddresses =
Dns.GetHostAddresses(serverUri.DnsSafeHost, AddressFamily.InterNetwork)
let serverEndpoint = IPEndPoint(serverAddresses[0], serverPort)
log "start sending..."
while not ct.IsCancellationRequested do
let! (msg: IUtf8SpanFormattable) = inbox.Receive()
let mutable size = 0
let ok = msg.TryFormat(buffer, &size, ReadOnlySpan.Empty, null)
if not ok || size = 0 then
log $"unnable to format %A{msg}"
let bufferSlice = buffer.AsMemory().Slice(0, size)
try
let! bytesSend = socket.SendToAsync(bufferSlice, serverEndpoint, ct).AsTask() |> Async.AwaitTask
log $"sent {bytesSend} bytes to {serverEndpoint}"
with :? OperationCanceledException ->
log "stopping sender..."
log "sender stopped!"
}),
ct
)
sender.Post (Guid.NewGuid())
stop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment