我正在尝试将两个UdpClients连接到一个端口,以便它们并行读取数据并在两个单独的队列中处理请求。但由于某种原因,只有一个客户端接收到数据包。
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
输出如下:
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
删除其中一个客户端会使另一个客户端很好地读取数据包。
这是一种让他们两个都接收数据包的方法吗?
答案 0 :(得分:2)
不,通常一旦将数据包从TCP / UDP堆栈中删除,就会被视为已处理。第一个客户端在收到它时将其删除,从操作系统和框架的角度来看,它已被处理,不会传递给更多的监听器。
您必须分两步实施您的解决方案:1接收数据的UDP侦听器并将其交给2个并行处理它的处理器。
答案 1 :(得分:1)
但由于某种原因,只有一个客户端接收到数据包。
嗯,原因是,每个IP堆栈的设计方式都是如此。
除了@Mau的建议,如果您的平台是Linux,iptables
也许可以实现您的目标:
答案 2 :(得分:0)
虽然两个答案都是正确的,但实际上可以使用UDP多播。但是,这要求网络中的路由器实际上支持多播。要使用多播,您可以在套接字上设置更多选项
//Creates a multicast publisher
let publisher multicastGroup ttl =
let client = new UdpClient()
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastGroup, IPAddress.Any))
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, ttl)
client
//Creates a multicast listener
let listener port multicastGroup =
let client = new UdpClient()
client.ExclusiveAddressUse <- false
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true)
client.Client.Bind(new IPEndPoint(IPAddress.Any, port))
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastGroup, IPAddress.Any))
client
然后您可以像在代码中一样使用发送和接收方法。有关此示例,请参阅here