为什么当我将重用地址设置为 true 时没有来自 BeginReceive 的回调?UDP

本文关键字:BeginReceive UDP 回调 true 设置 地址 为什么 | 更新日期: 2023-09-27 18:33:07

我正在为 UDP 接收和发送功能创建一个 C# 套接字,其中包含用于接收的异步回调函数。简单,对吧!花了一段时间才把所有的皱纹都熨平了,但它有效......好吧,只要你占领港口!我需要允许其他应用程序使用相同的端口号。没问题,对吧!有一个选项,SetSocketOption(...(用于ReuseAddress...

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

为什么当我将重用地址设置为 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);
      }
   }
}

为什么当我将重用地址设置为 true 时没有来自 BeginReceive 的回调?UDP

据我所知,你应该使用UdpClient,而不是使用Socket进行低级。

您还需要使用默认构造函数创建 UdpClient,以便能够更改 ExclusiveAddressUse 等设置。

这家伙有一个工作的例子:http://social.msdn.microsoft.com/Forums/en-US/fe830c54-30ab-4ae6-a86a-7c2a9ccd11cf/udpclient-more-than-one-on-the-same-port