一、定义单播端口、本地IP
public const int PortU = 1136;
public static IPAddress LocalIP; /* 本地绑定的IP */
public static List multiNetIpList = new List();
public const uint IOC_IN = 0x80000000;
public const uint IOC_VENDOR = 0x18000000;
二、定义组播地址和组播UDP客户端列表
private static List MulticastClientList = new List();
private class MulticastClient
{
public IPAddress ip;
public IPEndPoint multiEndPoint;
public UdpClient udp;
public int sourceIndex = 0;
}
private static Dictionary<int, UdpClient> UnicastClientDic = new Dictionary<int, UdpClient>();
三、UDP初始化网络、UDP单播、组播创建、退出
public static bool UdpInit(IPAddress LocalIP)
{
UDP.LocalIP = LocalIP;
return true;
}
private static UdpClient CreateUnicastUDP(int sourceIndex)
{
try
{
//由系统提供端口号
UdpClient udp = new UdpClient(0);
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
udp.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
udp.BeginReceive(UdpRecvFunc, sourceIndex);
return udp;
}
catch (System.Exception e)
{
throw new Exception("单播创建失败. ");
}
}
private static UdpClient CreateMulticastUDP(IPEndPoint muilAddr, IPAddress sourceIP)
{
try
{
UdpClient udp = new UdpClient(new IPEndPoint(sourceIP, 0));
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
udp.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
udp.JoinMulticastGroup(muilAddr.Address, sourceIP);
udp.Client.IOControl(IOControlCode.MulticastScope, new byte[] { Convert.ToByte(3) }, null);
udp.Client.IOControl(IOControlCode.MultipointLoopback, new byte[] { Convert.ToByte(false) }, null);
List obj = new List();
obj.Add(muilAddr);
obj.Add(sourceIP);
/false: 禁止回环 true: 允许回环/
udp.MulticastLoopback = false;
udp.BeginReceive(MutilCastRecvFunc, obj);
return udp;
}
catch (System.Exception e)
{
return null;
}
}
/不同的设备选择不同的本地IP/
public static bool UdpSetLocalIP(IPAddress localIP)
{
try
{
UDP.LocalIP = localIP;
return true;
}
catch (System.Exception e)
{
return false;
}
}
/UDP网络退出时需要调用关闭UDP网络连接/
public static bool UdpEnd()
{
foreach (UdpClient udp in UnicastClientDic.Values)
{
udp.Close();
}
UnicastClientDic.Clear();
foreach (MulticastClient client in MulticastClientList)
{
client.udp.Close();
}
MulticastClientList.Clear();
return true;
}
四、单播发送与接收
//UDPClient 的创建
public static bool InitUnicastClient(int sourceIndex)
{
if (!UnicastClientDic.ContainsKey(sourceIndex))
{
UnicastClientDic.Add(sourceIndex, CreateUnicastUDP(sourceIndex));
return true;
}
return false;
}
public static bool UdpSend(IPAddress IP, ref byte[] SendData, int length)
{
return UdpSend(new IPEndPoint(IP, UDP.PortU), ref SendData, length, 0);
}
//UDP单播数据发送
public static bool UdpSend(IPEndPoint addr, ref byte[] sendData, int length, int sourceIndex)
{
try
{
if (!UnicastClientDic.ContainsKey(sourceIndex))
{
UnicastClientDic.Add(sourceIndex, CreateUnicastUDP(sourceIndex));
}
UdpClient udp = UnicastClientDic[sourceIndex];
udp.Client.SendBufferSize = 1024 * 1024;
int i = udp.Send(sendData, length, addr);
InformUI.Inform2UI(sendData, length, sourceIndex);
}
catch (Exception ex)
{
return false;
}
return true;
}
/// UDP单播接收回调函数
private static void UdpRecvFunc(IAsyncResult Result)
{
int sourceIndex = (int)Result.AsyncState;
if (UnicastClientDic.ContainsKey(sourceIndex))
{
UdpClient udp = UnicastClientDic[sourceIndex];
try
{
System.Threading.Interlocked.Exchange(ref SubDevice.LastAliveTime, Environment.TickCount);
IPEndPoint remote = null;
byte[] Buffer = udp.EndReceive(Result, ref remote);
udp.BeginReceive(UdpRecvFunc, sourceIndex);
Protocal.AddDataToList1(remote, ref Buffer, sourceIndex);
}
catch (Exception ex)
{
udp.Close();
UnicastClientDic.Remove(sourceIndex);
}
}
}
五、组播发送与接收
public static bool MutilCastSend(IPEndPoint multAddr, byte[] SendData, int length)
{
try
{
GetMultiNetIp();
foreach (MultiNetIpDic mIPDic in multiNetIpList)
{
MulticastClient client = MulticastClientList.FirstOrDefault(m => m.ip.Equals(mIPDic.ip) && m.multiEndPoint.Equals(multAddr));
if (client == null)
{
client = new MulticastClient() { ip = mIPDic.ip, multiEndPoint = multAddr, udp = CreateMulticastUDP(multAddr, mIPDic.ip), sourceIndex = mIPDic.sourceIndex };
MulticastClientList.Add(client);
}
UdpClient udp = client.udp;
udp.BeginSend(SendData, SendData.Length, client.multiEndPoint, AsyncCallback =>
{
if (AsyncCallback.IsCompleted)
{
udp.EndSend(AsyncCallback);
}
}, null);
}
}
catch (Exception ex)
{
return false;
}
return true;
}
/// UDP组播接收回调函数
private static void MutilCastRecvFunc(IAsyncResult Result)
{
List obj = Result.AsyncState as List;
IPEndPoint multAddr = obj[0] as IPEndPoint;
IPAddress sourceIP = obj[1] as IPAddress;
MulticastClient client = MulticastClientList.FirstOrDefault(m => m.ip.Equals(sourceIP) && m.multiEndPoint.Equals(multAddr));
if (sourceIP != null && client!=null)
{
UdpClient udpM = client.udp;
try
{
IPEndPoint Remote = null;
byte[] Buffer = udpM.EndReceive(Result, ref Remote);
Protocal.AddDataToList1(Remote, ref Buffer, client.sourceIndex);
udpM.BeginReceive(MutilCastRecvFunc, obj);
}
catch
{
udpM.Close();
MulticastClientList.Remove(client);
}
}
}
UDP单播和组播通讯之C#设计笔记(十四)
于 2022-11-18 12:36:39 首次发布