哪个具有SocketOptionName.ReuseAddress的UdpClient实际接受数据?

时间:2019-03-28 11:29:02

标签: c# sockets udp udpclient

我需要在特定端点地址上接收数据。但是,当我响应请求时,我需要从接收数据的同一端点发送数据(否则另一方将忽略它)。

问题是我不想顺序处理请求,因此一个线程仅接收数据以将其传递给另一个处理请求并发送响应的线程。 AFAIK,不能同时使用同一UdpClient实例,因此我想到的唯一想法是,每次我想向发送方发送响应时都创建一个新实例。

要实现我想要的目的,我可以通过以下方式创建客户端( SocketOptionName.ReuseAddress ):

var udpClient = new UdpClient
{
    Client = CreateBoundUdpSocket()
};

public static Socket CreateBoundUdpSocket()
{
    var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);

    socket.ExclusiveAddressUse = false;
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

    socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, optionValue: false);

    socket.Bind(new IPEndPoint(IPAddress.Loopback, 1010));
    return socket;
}

问题是,用于响应的UDP客户端仅针对该单个操作创建,然后立即进行处理。我如何确定只有第一个创建的实例将接受数据,而其他实例不接受数据?我不想丢失任何数据包。

根据我执行的测试,只有第一个实例收到任何东西。即使将接收缓冲区设置为0,其他实例也不会获取任何数据。仅当我关闭第一个实例时,下一个创建的实例才会获取数据。似乎创建顺序很重要,因为每当我关闭当前接收数据的实例时,下一个创建的实例就会开始获取它(不是随机的,而是下一个)。

长话短说,我可以确定我创建的第一个实例将接收数据吗?

-编辑-

要阐明我的一般做法(可能不正确):

var server = new UdpClient { Client = CreateBoundUdpSocket() };

while (true)
{
    IPEndPoint sender = null;
    var data = server.Receive(ref sender);

    Task.Factory.StartNew
    (
        (object param) =>
        {
            // [process the request]
            var request = (Tuple<IPEndPoint, byte[]>)param;

            // and send a response
            using (var client = new UdpClient { Client = CreateBoundUdpSocket() })
            {
                var someResponse = new byte[] { };
                client.Send(someResponse, someResponse.Length, request.Item1);
            }
        },
        state: new Tuple<IPEndPoint, byte[]>(sender, data)
    );
}

0 个答案:

没有答案