我正在为 UDP 接收和发送功能创建一个 C# 套接字,并为接收提供异步回调函数。很简单,对!消除所有皱纹需要一段时间,但它确实有效......好吧,只要你占领港口!我需要允许其他应用程序使用相同的端口号。没问题,对!有一个选项,SetSocketOption(...) for 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);
}
}
}