• udp单播,广播,多播实现(ReceiveFromAsync,SendToAsync)


    注意:客户端和服务器实现基本一致,本地host和port和多播的host和port可以一样

    (1)多播

    1.将本地host加入多播组中,只有加入多播组的成员才能接受同组的节点发送的多播

    MulticastOption mcastOption = new MulticastOption(IPAddress.Parse(MultiCastHost), IPAddress.Parse(localHost));
    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption);

    2.将本地host移出多播组中

    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, mcastOption);

    3.多播生存时间 millisecond

    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 10);

    发送信息指定MultiCastHost发送

     (2)广播

    开启广播

    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);

     发送信息指定255.255.255.255发送

    参考:MSDN

        public class UdpServiceSocket
        {
            private readonly string broadCastHost = "255.255.255.255";
    
            //接收数据事件
            public Action<string> recvMessageEvent = null;
            //发送结果事件
            public Action<int> sendResultEvent = null;
    
            //接收缓存数组
            private byte[] recvBuff = null;
            //发送缓存数组
            private byte[] sendBuff = null;
            //用于发送数据的SocketAsyncEventArgs
            private SocketAsyncEventArgs sendEventArg = null;
            //用于接收数据的SocketAsyncEventArgs
            private SocketAsyncEventArgs recvEventArg = null;
            //监听socket
            private Socket socket = null;
            //用于socket发送和接收的缓存区大小
            private int bufferSize = 1024;
            //udp服务器绑定地址
            private string localHost = "";
            //udp服务器监听端口
            private int localPort = 0;
            //udp广播组地址
            private string MultiCastHost = "";
            //udp广播组端口
            private int MultiCastPort = 0;
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="bufferSize">用于socket发送和接受的缓存区大小</param>
            public UdpServiceSocket()
            {
                //设置用于发送数据的SocketAsyncEventArgs
                sendBuff = new byte[bufferSize];
                sendEventArg = new SocketAsyncEventArgs();
                sendEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                sendEventArg.SetBuffer(sendBuff, 0, bufferSize);
                //设置用于接受数据的SocketAsyncEventArgs
                recvBuff = new byte[bufferSize];
                recvEventArg = new SocketAsyncEventArgs();
                recvEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
                recvEventArg.SetBuffer(recvBuff, 0, bufferSize);
            }
    
            /// <summary>
            ///  开启udp服务器,等待udp客户端数据(设置广播)
            /// </summary>
            public void Start(string localHost, int localPort)
            {
                if (string.IsNullOrEmpty(localHost))
                    throw new ArgumentNullException("localHost cannot be null");
                if (localPort < 1 || localPort > 65535)
                    throw new ArgumentOutOfRangeException("localPort is out of range");
    
                this.localHost = localHost;
                this.localPort = localPort;
    
                try
                {
                    socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    
                    //设置广播
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
    
                    IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(localHost), localPort);
                    socket.Bind(endpoint);//设置监听地址和端口
                    StartRecvFrom();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            /// <summary>
            ///  开启udp服务器,等待udp客户端数据(设置多播,广播)
            /// </summary>
            /// <param name="ip"></param>
            /// <param name="port"></param>
            public void Start(string localHost, int localPort, string MultiCastHost, int MultiCastPort)
            {
                if (string.IsNullOrEmpty(localHost))
                    throw new ArgumentNullException("localHost cannot be null");
                if (localPort < 1 || localPort > 65535)
                    throw new ArgumentOutOfRangeException("localPort is out of range");
    
                if (string.IsNullOrEmpty(MultiCastHost))
                    throw new ArgumentNullException("MultiCastHost cannot be null");
                if (MultiCastPort < 1 || MultiCastPort > 65535)
                    throw new ArgumentOutOfRangeException("MultiCastPort is out of range");
    
                this.localHost = localHost;
                this.localPort = localPort;
                this.MultiCastHost = MultiCastHost;
                this.MultiCastPort = MultiCastPort;
    
                try
                {
                    socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    
                    //设置广播
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
    
                    //设置多播
                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);
                    MulticastOption mcastOption = new MulticastOption(IPAddress.Parse(MultiCastHost), IPAddress.Parse(localHost));
                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption);
    
                    IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(localHost), localPort);
                    socket.Bind(endpoint);//设置监听地址和端口
                    StartRecvFrom();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            /// <summary>
            /// 开始接受udp客户端发送的数据
            /// </summary>
            private void StartRecvFrom()
            {
                recvEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                bool willRaiseEvent = socket.ReceiveFromAsync(recvEventArg);
                if (!willRaiseEvent)
                {
                    ProcessReceive(recvEventArg);
                }
            }
    
            /// <summary>
            /// socket.sendAsync和socket.recvAsync的完成回调函数
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void IO_Completed(object sender, SocketAsyncEventArgs e)
            {
                switch (e.LastOperation)
                {
                    case SocketAsyncOperation.ReceiveFrom:
                        ProcessReceive(e);
                        break;
                    case SocketAsyncOperation.SendTo:
                        ProcessSend(e);
                        break;
                    default:
                        throw new ArgumentException("The last operation completed on the socket was not a receive or send");
                }
            }
    
            /// <summary>
            /// 处理接收到的udp客户端数据
            /// </summary>
            /// <param name="e"></param>
            private void ProcessReceive(SocketAsyncEventArgs e)
            {
                if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
                {
                    if (recvMessageEvent != null)
                        //一定要指定GetString的长度
                        recvMessageEvent(Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred));
    
                    StartRecvFrom();
                }
                else
                {
                    Restart();
                }
            }
    
            /// <summary>
            /// 处理udp服务器发送的结果
            /// </summary>
            /// <param name="e"></param>
            private void ProcessSend(SocketAsyncEventArgs e)
            {
                AsyncUserToken token = (AsyncUserToken)e.UserToken;
                if (e.SocketError == SocketError.Success)
                {
                    if (sendResultEvent != null)
                        sendResultEvent(e.BytesTransferred);
                }
                else
                {
                    if (sendResultEvent != null)
                        sendResultEvent(e.BytesTransferred);
                    Restart();
                }
            }
    
            /// <summary>
            /// 关闭udp服务器
            /// </summary>
            public void CloseSocket()
            {
                if (socket == null)
                    return;
    
                try
                {
                    socket.Shutdown(SocketShutdown.Both);
                }
                catch { }
    
                try
                {
                    socket.Close();
                }
                catch { }
            }
    
            /// <summary>
            /// 重新启动udp服务器
            /// </summary>
            public void Restart()
            {
                CloseSocket();
                if (string.IsNullOrEmpty(MultiCastHost))
                    Start(localHost, localPort, MultiCastHost, MultiCastPort);
                else
                    Start(localHost, localPort);
            }
    
            /// <summary>
            /// 发送广播
            /// </summary>
            /// <param name="message"></param>
            public void SendMessageByBroadcast(string message)
            {
                if (socket == null)
                    throw new ArgumentNullException("socket cannot be null");
                if (string.IsNullOrEmpty(message))
                    throw new ArgumentNullException("message cannot be null");
    
                byte[] buff = Encoding.UTF8.GetBytes(message);
                if (buff.Length > bufferSize)
                    throw new ArgumentOutOfRangeException("message is out off range");
    
                sendEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(broadCastHost), localPort);
                buff.CopyTo(sendEventArg.Buffer, 0);
                sendEventArg.SetBuffer(0, buff.Length);
                bool willRaiseEvent = socket.SendToAsync(sendEventArg);
                if (!willRaiseEvent)
                {
                    ProcessSend(sendEventArg);
                }
            }
    
            /// <summary>
            /// 发送单播
            /// </summary>
            /// <param name="message"></param>
            public void SendMessageByUnicast(string message, string destHost, int destPort)
            {
                if (socket == null)
                    throw new ArgumentNullException("socket cannot be null");
                if (string.IsNullOrEmpty(message))
                    throw new ArgumentNullException("message cannot be null");
                if (string.IsNullOrEmpty(destHost))
                    throw new ArgumentNullException("destHost cannot be null");
                if (destPort < 1 || destPort > 65535)
                    throw new ArgumentOutOfRangeException("destPort is out of range");
    
                byte[] buff = Encoding.UTF8.GetBytes(message);
                if (buff.Length > bufferSize)
                    throw new ArgumentOutOfRangeException("message is out off range");
    
                sendEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(destHost), destPort);
                buff.CopyTo(sendEventArg.Buffer, 0);
                sendEventArg.SetBuffer(0, buff.Length);
                bool willRaiseEvent = socket.SendToAsync(sendEventArg);
                if (!willRaiseEvent)
                {
                    ProcessSend(sendEventArg);
                }
            }
    
            /// <summary>
            /// 发送组播(多播)
            /// </summary>
            /// <param name="message"></param>
            public void SendMessageByMulticast(string message)
            {
                if (socket == null)
                    throw new ArgumentNullException("socket cannot be null");
                if (string.IsNullOrEmpty(message))
                    throw new ArgumentNullException("message cannot be null");
                if (string.IsNullOrEmpty(MultiCastHost))
                    throw new ArgumentNullException("MultiCastHost cannot be null");
                if (MultiCastPort < 1 || MultiCastPort > 65535)
                    throw new ArgumentOutOfRangeException("MultiCastPort is out of range");
    
                byte[] buff = Encoding.UTF8.GetBytes(message);
                if (buff.Length > bufferSize)
                    throw new ArgumentOutOfRangeException("message is out off range");
    
                sendEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(MultiCastHost), MultiCastPort);
                buff.CopyTo(sendEventArg.Buffer, 0);
                sendEventArg.SetBuffer(0, buff.Length);
                bool willRaiseEvent = socket.SendToAsync(sendEventArg);
                if (!willRaiseEvent)
                {
                    ProcessSend(sendEventArg);
                }
            }
        }
    

      

      

  • 相关阅读:
    Codeforces Round #636 D. Constant Palindrome Sum(差分/好题)
    Codeforces Round #636 C. Alternating Subsequence
    Codeforces Round #636 B. Balanced Array(水)
    Codeforces Round #636 A. Candies(水)
    洛谷P2136 拉近距离(负环判定)
    P2850 [USACO06DEC]Wormholes G(负环判定)
    架构--缓存知识
    集群-架构
    ELK-第二集
    Linux下的I/O复用与epoll详解
  • 原文地址:https://www.cnblogs.com/yaosj/p/11196794.html
Copyright © 2020-2023  润新知