Почему НЕТ обратного вызова от BeginReceive, когда я установил для ReuseAddress значение true? UDP

Я создаю сокет C# для возможностей получения и отправки UDP с функциями асинхронного обратного вызова для получения. Просто, правильно! Потребовалось некоторое время, чтобы разгладить все морщины, но это работает... Ну, пока вы держите порт! Мне нужно разрешить другим приложениям использовать тот же номер порта. Нет проблем, верно! Для этого есть опция SetSocketOption(...) для ReuseAddress...

udpClient.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.ReuseAddress, true);

Почему, когда я устанавливаю для ReuseAddress значение true, функция обратного вызова больше не срабатывает?

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using CSharpUtilityLibrary.Utilities;

namespace CSharpNIU.Sockets
{
      public class PacketEventArgs : EventArgs {
      public byte[] Bytes { get; set; }
      public PacketEventArgs(byte[] bytes)
      {
         Bytes = bytes;
      }
   }

   public delegate void PacketEventHandler(object sender, PacketEventArgs e);

   // State object for reading client data asynchronously
   public class StateObject
   {
      // Client  socket.
      public Socket workSocket = null;

      // Size of receive buffer.
      public const int BufferSize = 1553;

      // Receive buffer.
      public byte[] buffer = new byte[BufferSize];
   }

   public class UDPSocket
   {
      // Thread signal.
      public ManualResetEvent allDone = new ManualResetEvent(false);

      public String ApplicationName { get; set; }
      public Form ParentForm { get; set; }
      public Network ApplicationNetwork { get; set; }
      private ConfigGeneric Config { get; set; }
      private Socket udpClient = null;

      public UDPSocket(ConfigGeneric config, String applicationName)
      {
         Config = config;

         ApplicationDetails appDetails = config.GetApplicationByName(applicationName);
         if (appDetails == null)
            return;

         ApplicationNetwork = config.GetNetworkByName(appDetails._network);
         if (ApplicationNetwork == null) return;
      }

      public void StartListening()
      {
         // Data buffer for incoming data.
         byte[] bytes = new Byte[1024];

         IPAddress ipAddress = IPAddress.Parse(ApplicationNetwork._networkAddress);
         IPEndPoint localEndPoint = new IPEndPoint(ipAddress, ApplicationNetwork._receivePort);

         // Create a UDP Socket
         udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

         // Bind the socket to the local endpoint
         try
         {
            // Set the event to nonsignaled state.
            allDone.Reset();

            // Start an asynchronous socket to listen for connections.
            allDone.Set();
            StateObject stateObject = new StateObject();
            stateObject.workSocket = udpClient;
//------> The line Below causes the begin receive to not call ReadCallback <-------//
            udpClient.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.ReuseAddress, true);
//------> The line Above causes the begin receive to not call ReadCallback <-------//
            udpClient.Bind(localEndPoint);

            udpClient.BeginReceive(stateObject.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), stateObject);

            // Wait until a connection is made before continuing.
            allDone.WaitOne();
         }
         catch (Exception e)
         {
            Console.WriteLine(e.ToString());
         }
      }

      public void ReadCallback(IAsyncResult ar)
      {
         String content = String.Empty;

         // Retrieve the state object and the handler socket from the asynchronous state object.
         StateObject state = (StateObject)ar.AsyncState;
         Socket handler = state.workSocket;

         // Read data from the client socket. 
         int bytesRead = handler.EndReceive(ar);

         if (bytesRead > 0)
         {
            PacketEventArgs packetEventArgs = new PacketEventArgs(state.buffer);
            OnRecevedPacket(packetEventArgs);

            // There  might be more data, so store the data received so far.
            udpClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state);
         }
      }

      // Event Handlers
      public event PacketEventHandler ReceiveCallback;

      protected virtual void OnRecevedPacket(PacketEventArgs e)
      {
         if (ReceiveCallback != null)
            ReceiveCallback(this, e);
      }

      public void Send(byte[] bytes)
      {
         // Begin sending the data to the remote device.
         IPAddress ipAddress = IPAddress.Parse(ApplicationNetwork._broadcastAddress);
         IPEndPoint endPoint = new IPEndPoint(ipAddress, ApplicationNetwork._receivePort);

         udpClient.SendTo(bytes, endPoint);
      }
   }
}

person Dainon    schedule 26.09.2013    source источник
comment
Обновление Я только что заметил, что SetSocketOption выдает исключение «Был указан недопустимый аргумент», что предотвращает вызов BeginReceive. У меня есть еще что исследовать.   -  person Dainon    schedule 26.09.2013
comment
Я не нашел ничего, что говорило бы о том, почему эта строка имеет недопустимый аргумент. Я заметил несколько сообщений, в которых люди использовали UdpClient и устанавливали параметр сокета с помощью SocketOptionLevel.Socket. Это избавляет от исключения, но по-прежнему нет обратного вызова для функции ReadCallback.   -  person Dainon    schedule 27.09.2013


Ответы (1)


Из того, что я могу сказать, вы должны использовать UdpClient вместо низкого уровня с Socket.

Вам также необходимо создать UdpClient с конструктором по умолчанию, чтобы иметь возможность изменять такие параметры, как ExclusiveAddressUse.

У этого парня есть рабочий пример: тот-же-порт" rel="nofollow">http://social.msdn.microsoft.com/Forums/en-US/fe830c54-30ab-4ae6-a86a-7c2a9ccd11cf/udpclient-more-than-one-on- тот же порт

person bruteostrich    schedule 27.09.2013