Исключение привязки сокета C# UDP

Я пытаюсь создать программу для беспроводной сети (adhoc во всем, кроме имени). Большая часть сети будет иметь дело с обменом сообщениями TCP, но для определения всех соседних IP-адресов (поскольку они будут неизвестны при запуске) я предпочитаю использовать широковещательную рассылку UDP для первоначальных сообщений обнаружения. Этот код, по большей части, не имеет значения, так как первоначальное тестирование, казалось, работало, и в настоящее время я его не называю.

Ниже приведен раздел для получения и регистрации IP-адресов соседей.

protected override void ReceiveMessageUDP()
    {
        while (live)
        {
            try
            {
                UdpListener = new UdpClient(_PORTRECEIVE);
                UdpListener.EnableBroadcast = true;
                Socket socket = UdpListener.Client;
                IPEndPoint endPoint1 = new IPEndPoint(IPAddress.Loopback, _PORTRECEIVE);
                IPEndPoint endPoint2 = new IPEndPoint(IPAddress.Any, _PORTRECEIVE);
                socket.Bind(endPoint2);
                socket.Listen(25);
                Socket connected = socket.Accept();
                byte[] buffer = new byte[1024];
                int length = connected.Receive(buffer);

                IPAddress remoteIP = ((IPEndPoint)connected.RemoteEndPoint).Address;
                if (!ipAddresses.Contains(remoteIP))
                    ipAddresses.Add(remoteIP);

                Message.Add(Encoding.ASCII.GetString(buffer, 0, length));
            }
            catch (SocketException e) { Console.WriteLine(e.ErrorCode); }
            catch (Exception) { }
        }
    }

Я тестировал оба IPEndPoints, и независимо от того, как я его настроил, привязка завершается с ошибкой SocketException.ErrorCode 10022 Коды ошибок сокета Windows. Это недопустимый аргумент, но я не понимаю, что это значит, поскольку требуемый аргумент — это EndPoint.

Это не удается при первом запуске, поэтому я не пытаюсь переназначить порт.


person Scott S    schedule 09.11.2010    source источник


Ответы (2)


Вы уже привязали порт к UdpCLient, когда создавали его. Затем вы не можете привязать один и тот же порт к отдельному IPEndPoint.

UdpListener = new UdpClient(_PORTRECEIVE);  // binds port to UDP client
...
IPEndPoint endPoint2 = new IPEndPoint(IPAddress.Any, _PORTRECEIVE);
socket.Bind(endPoint2);  // attempts to bind same port to end point

Если вы хотите сделать это таким образом, создайте и привяжите IPEndPoint, а затем создайте UdpClient с ним вместо порта.

IPEndPoint endPoint2 = new IPEndPoint(IPAddress.Any, _PORTRECEIVE);
socket.Bind(endPoint2);  // bind port to end point

UdpListener = new UdpClient(endPoint2);  // binds port to UDP client via endpoint

Я не уверен, почему вы также настраиваете другую конечную точку endPoint1 на том же порту. Это, вероятно, вызовет проблемы в будущем, если и когда вы попытаетесь использовать это.

person Steve Townsend    schedule 09.11.2010
comment
Я на 95% новичок в том, чтобы делать что-либо TCP/UDP/Socket, поэтому я летал вслепую около 2 недель, выясняя это. Как только я создаю UdpClient с конечной точкой, я затем привязываю сокет к вторичной конечной точке? - person Scott S; 10.11.2010
comment
Приведенная выше логика (моя версия) привязывает сокет к этой конечной точке, а затем настраивает клиент на конечной точке — сокет все еще привязан в этой точке. Вы также можете использовать идентификатор порта = 0, и система будет использовать любой свободный локальный порт, этот вариант, вероятно, будет проще для вас на endPoint1. Взгляните на пример кода в MSDN здесь — msdn.microsoft.com/en -us/library/k227d11f.aspx — есть множество примеров, которые могут помочь вам разобраться в этом. Ознакомьтесь с общей информацией для начинающих TCP/UDP: msdn.microsoft.com/ en-us/library/c19ex43h.aspx - person Steve Townsend; 10.11.2010
comment
Я создаю множество таких переменных во время тестирования — просто присваиваю им разные числа в конце, чтобы быстро выбирать между ними во время тестирования. Что касается программы - я изменил ее с вашими предложениями, попробовав первую, затем вторую и, наконец, используя 0 в качестве порта для UdpClient. Я снова получил тот же код ошибки для socket.Bind. - person Scott S; 10.11.2010
comment
Разобрался, UDP не разрешает привязку и прочее. - person Scott S; 10.11.2010
comment
@Scott S - рад слышать, что ты преодолел этот горб - person Steve Townsend; 10.11.2010
comment
re: UDP не разрешает привязку. Проще говоря, не требует привязки. Разрешено привязывать сокет, который еще не привязан. И вы можете сделать это, если хотите контролировать, какая конечная точка используется для отправки сообщения UDP. Проблема в том, что UdpClient уже вызывает Client.Bind(...). - person Jesse Chisholm; 26.09.2014

Я согласен со Стивом. Однако вы утверждаете, что

«UDP не разрешает привязку или что-то в этом роде».

Но это так. Вы можете привязать любой сокет (udp или нет) к любому сетевому интерфейсу. Стив дал подсказку, как это сделать. Вот как я это делаю:

LocalEP = new IPEndPoint(<local IP>, _PORTRECEIVE) ;
listener = New UdpClient(LocalEP) ;

Как отметил Стив, после создания экземпляра UdpClient повторная привязка к другому интерфейсу невозможна. Хитрость заключается в том, чтобы сообщить конструктору о необходимости привязки к интерфейсу, который вы хотите заранее. Замените IP-адрес локального интерфейса, который вы хотите использовать.

Конечно, это полезно только тогда, когда у вас есть (или может быть) несколько сетевых интерфейсов и вы хотите использовать определенный. В противном случае я видел, что интерфейс с действительным шлюзом в Интернет обычно является тем, к которому клиенты привязываются по умолчанию. И это, как правило, правильно.

Роберто

person Roberto Mejia    schedule 22.08.2013
comment
Также полезно, если вы хотите отправить с определенного порта, даже если вы привязаны к IPAddress.Any. - person Jesse Chisholm; 26.09.2014