我正在创建一个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);
}
}
}
答案 0 :(得分:0)
据我所知,您应该使用UdpClient而不是使用Socket进行低级别。
您还需要使用默认构造函数创建UdpClient,以便能够更改ExclusiveAddressUse等设置。