Search code examples
.netsocketsf#udpudpclient

Process UDP packet by two clients connected to IPAddress.Any and 127.0.0.1


I'm trying to connect two UdpClients to one port so they read the data in parallel and handle the requests in two separate queues. But for some reason only one of the clients receives the packets.

let listen (local:IPEndPoint) =
    async {
        use client = new UdpClient()
        client.ExclusiveAddressUse <- false
        client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)
        client.Client.Bind(local);

        printfn "Listen: %A" local.Address

        while true do
            let mutable remote = local
            client.Receive(&remote) |> ignore
            printfn "%A: %A" local.Address remote.Address
    }

Async.Parallel [
    listen(new IPEndPoint(IPAddress.Any, 5353));
    listen(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5353));
    async {
        while true do
            do! Async.Sleep 500

            use senderUC = new UdpClient()
            senderUC.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)
            senderUC.Send([|byte(1)|], 1, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5353)) |> ignore

            printfn "sent to 127.0.0.1"
    }
] |> Async.RunSynchronously |> ignore


Thread.Sleep 10000

The output looks like:

Listen: 127.0.0.1
Listen: 0.0.0.0
sent to 127.0.0.1
127.0.0.1: 127.0.0.1
...
sent to 127.0.0.1
127.0.0.1: 127.0.0.1

Removing one of the clients makes another one reads the packets well.

Is here a way to make both of them receive the packets?


Solution

  • No, in general once a packet is 'removed from the TCP/UDP stack' is considered processed. The first client removes it when it receives it and from the point of view of the OS and the framework, it's handled and won't be delivered to more listeners.

    You'll have to implement your solution in 2 steps: 1 UDP listener that receives the data and hands it over to 2 processors that handle it in parallel.