2010-11-09 2 views
0

Прежде чем кто-нибудь спросит, я просмотрел этот сайт совсем немного и использовал google, широко ищущий ответ безрезультатно.C# UDP Socket Bind Exception

Я пытаюсь создать программу для беспроводной сетки (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 и независимо от того, как я установил его вверх, Bind терпит неудачу с SocketException.ErrorCode 10022 Windows Socket Error Codes. Это недопустимый аргумент, но я смущен тем, что это означает, что в качестве аргумента требуется EndPoint.

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

ответ

1

Вы уже связали порт с 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 на том же порту. Это, вероятно, вызовет проблемы, если и когда вы попытаетесь использовать это.

+0

Я 95% новый, чтобы делать какие-либо TCP/UDP/сокет ничего, так что я летаю слеп около 2 недель выяснить это. Как только я создаю UdpClient с EndPoint, я затем привязываю Socket к вторичной конечной точке? –

+0

Логика выше (моя версия) связывает сокет с этой конечной точкой, а затем устанавливает клиент на конечной точке - сокет все еще связан в этой точке. Вы также можете использовать порт id = 0, и система будет использовать любой свободный локальный порт, этот вариант, вероятно, будет проще для вас на 'endPoint1'.Взгляните на пример кода в MSDN здесь - http://msdn.microsoft.com/en-us/library/k227d11f.aspx - есть много примеров, которые могли бы помочь вам понять это. Взгляните сюда на общую информацию о старте TCP/UDP - http://msdn.microsoft.com/en-us/library/c19ex43h.aspx –

+0

Я создаю множество переменных, подобных этому при тестировании, просто давая им разные номера в конце чтобы быстро выбирать между ними во время тестирования. Что касается программы - я изменил ее с вашими предложениями, попробовав первый, затем второй и, наконец, используя 0 в качестве порта для UdpClient. Я получил тот же код ошибки для socket.Bind снова. –

1

Я согласен с steve. Тем не менее, вы заявляете, что

«UDP не разрешает переплет или прочее».

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

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

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

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

Роберто

+0

Также полезно, если вы хотите отправить с определенного порта, даже если вы привязаны к IPAddress.Any. –