【问题标题】:C# UdpClient.Connect() raises exception on 2nd callC# UdpClient.Connect() 在第二次调用时引发异常
【发布时间】:2023-01-12 20:48:41
【问题描述】:

我试图将单个 UdpClient 发送到从本地主机到本地主机的几个不同的开放 UDP 套接字。然而,在第一个版本中,只发送了循环的第一条消息,其余的甚至都没有发出。

尝试隔离错误时,第二次调用 udpClient.Connect() 会引发 SocketException 指向错误 WSAEISCONN 10056

UdpClient.Connect()here的官方文档在备注部分说明如果要发送到不同的端点,请再次调用Connect。然而,这与错误告诉我的相反。

那么这只是Connect方法文档中的一个错误,还是我在这里遗漏了什么?

太快的请求应该不是问题,每 3 秒只有 3 个请求,并且当我使用正常的 Send(buffer) 调用时,应该没有等待发送到前一个端点的数据包。

重现的简单示例(我使用 .net 6,Win10):

using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpClientIssue;

internal class Program
{
    static void Main(string[] args)
    {
        var sender = CreateSender(3_000, 40001, 40002, 40003);
        var reciverA = CreateReciver("ReciverA", 40001);
        var reciverB = CreateReciver("ReciverB", 40002);
        var reciverC = CreateReciver("ReciverC", 40003);

        reciverA.Start();
        reciverB.Start();
        reciverC.Start();
        sender.Start();

        sender.Join();
    }

    static void Reciver(int port)
    {
        var localEP = new IPEndPoint(IPAddress.Loopback, port);
        using var listener = new UdpClient(localEP);
        var buff = new byte[1024];

        while (true)
        {
            var senderEP = new IPEndPoint(IPAddress.None, 0);
            var data = listener.Receive(ref senderEP);
            var message = Encoding.UTF8.GetString(data);
            Console.WriteLine($"Recived at {port}: {message}");
        }
    }

    static void Sender(int interval_ms, params int[] ports)
    {
        int messageNumber = 0;
        while (true)
        {
            Thread.Sleep(interval_ms);
            using (var udpClient = new UdpClient())
            {
                foreach (var remotePort in ports)
                {
                    var message = $"Message {++messageNumber} to {remotePort}";
                    var sendBuffer = Encoding.UTF8.GetBytes(message);
                    Console.WriteLine($"Sending to {remotePort}: {message}");

                    var remoteEP = new IPEndPoint(IPAddress.Loopback, remotePort);
                    //This errors on second iteration
                    //udpClient.Connect(remoteEP);
                    //udpClient.Send(sendBuffer);

                    //This works
                    udpClient.Send(sendBuffer, remoteEP);
                }
            }
            messageNumber += 100 - ports.Length;
        }
    }

    static Thread CreateReciver(string name, int port)
    {
        var ts = new ThreadStart(() => Reciver(port));
        var t = new Thread(ts)
        {
            Name = name
        };
        return t;
    }

    static Thread CreateSender(int interval_ms, params int[] ports)
    {
        var ts = new ThreadStart(() => Sender(interval_ms, ports));
        var t = new Thread(ts)
        {
            Name = "Sender"
        };
        return t;
    }
}

【问题讨论】:

    标签: c# networking udp


    【解决方案1】:

    我相信这是文档中的错误。此错误消息的描述说:

    套接字已连接。 在已连接的套接字上发出连接请求

    如果套接字已连接,源代码会明确抛出此异常并显示此错误代码。

    Here你看到它只是转发连接到Socket

    public void Connect(IPEndPoint endPoint)
    {
        ThrowIfDisposed();
    
        ArgumentNullException.ThrowIfNull(endPoint);
    
        CheckForBroadcast(endPoint.Address);
        Client.Connect(endPoint);
        _active = true;
    }
    

    Socket.Connectsee 如果套接字已经连接,它会抛出这个错误:

    if (_isConnected)
    {
        throw new SocketException((int)SocketError.IsConnected);
    }
    

    幸运的是,您已经知道执行此操作的更好方法 - 只需将远程端点传递给 Send 调用即可。 UDP 无论如何都是无连接协议,因此调用 Connect 仅设置默认远程端点并且不执行实际连接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多