基于UDP协议的Socket服务器

来源:互联网 发布:新倩女幽魂网游mac 编辑:程序博客网 时间:2024/06/08 20:48

      上篇文章介绍了自己开发的基于TCP协议的服务器,也具有一定的扩展性;既然做了TCP的,那自然就得把UDP的也研究下,因此本篇文章将探讨下基于UDP协议的服务器。

       废话少说,下面开始介绍思路,由于UDP是无连接的,所以相对于TCP协议的服务器就简单很多,不需要去监听客户端,也不需要对会话进行维护,只需要对数据进行相应的处理就可以;因此整体思路就很明显了,用异步方式来接收客户端的数据,将数据放入队列中,用一个线程组来处理队列中的数据,每次从队列中取一个数据包进行处理,对于线程组中线程数可根据实际情况设定,首先给出成员定义:

       private Socket server = null;       private bool serverStart = false;//服务器是否启动        private int serverPort = 3130;//服务器端口        private int clientPort = 3131;//远程客户端端口        private IPAddress localIp;//服务器绑定的IP地址        private string brodcastIp;//广播IP地址        private byte[] tempReceiveData = null;//临时数据接收器        private EndPoint tempRemotePoint = null;//远程客户端        private Queue<BufferData> receivedBuffer;//数据缓冲区        private Thread[] threadDataHandler;//数据处理线程        private int threadDataHandlerNum = 1;//数据处理线程数        private IDataHandler iRceivedDataHandler = null;//数据处理接口        private Mutex m_ServerMutex;  // 只能有一个服务器

       
            启动服务器后,绑定端口,启动数据处理线程组,开始异步接收数据:

      

        /// <summary>        /// 启动服务器        /// </summary>        public void Start()        {            if (this.serverStart)            {                return;//服务器已经启动            }            this.server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);            this.tempReceiveData = new byte[this.server.ReceiveBufferSize];            IPAddress[] ip = Dns.GetHostAddresses(Dns.GetHostName());            IPEndPoint addr = new IPEndPoint(ip[0], this.serverPort);            this.localIp = ip[0];            //算出广播IP地址            string str = this.localIp.ToString();            int len = str.LastIndexOf('.');            str = str.Substring(0, len + 1);            this.brodcastIp = str + "255";            //绑定IP,端口            this.server.Bind(addr);            this.serverStart = true;            this.threadDataHandler = new Thread[this.threadDataHandlerNum];            for (int i = 0; i < this.threadDataHandlerNum; i++)            {                this.threadDataHandler[i] = new Thread(new ThreadStart(this.HandlerReceivedData));                this.threadDataHandler[i].Start();            }            this.AsyncBeginReceive();//开始接收数据        }

     

              异步接收数据及其回调函数:

 

       /// <summary>        /// 异步接收数据        /// </summary>        private void AsyncBeginReceive()        {            try            {                if (this.serverStart)                {                    this.server.BeginReceiveFrom(this.tempReceiveData, 0, this.server.ReceiveBufferSize, SocketFlags.None, 
                    ref this.tempRemotePoint, this.AsyncReceiveCallback, this);                }            }            catch { }        }        /// <summary>        /// 异步接收数据的回调函数        /// </summary>        /// <param name="iar"></param>        private void AsyncReceiveCallback(IAsyncResult iar)        {            try            {                iar.AsyncWaitHandle.Close();                if (this.serverStart)                {                    AsyncBeginReceive();                    int byteReadLen = this.server.EndReceiveFrom(iar, ref this.tempRemotePoint);                    byte[] temp = new byte[byteReadLen];                    Array.Copy(this.tempReceiveData, temp, byteReadLen);                    BufferData buffer = new BufferData(this.tempRemotePoint, temp);                    this.receivedBuffer.Enqueue(buffer);                }            }            catch            { }        }


           异步发送数据及其回调函数:

        /// <summary>        /// 开始异步发送数据        /// </summary>        /// <param name="buffer"></param>        private void AsyncBeginSend(IPAddress ip, string data)        {            try            {                byte[] byteData = Encoding.ASCII.GetBytes(data);                EndPoint iep = (EndPoint)new IPEndPoint(ip, this.clientPort);                this.server.BeginSendTo(byteData, 0, byteData.Length, SocketFlags.None, iep, 
                 new AsyncCallback(this.AsyncSendCallback), this);            }            catch { }        }        /// <summary>        /// 开始异步发送数据        /// </summary>        /// <param name="ip"></param>        /// <param name="data"></param>        private void AsyncBeginSend(string ip, int port, string data)        {            try            {                byte[] byteData = Encoding.ASCII.GetBytes(data);                EndPoint iep = (EndPoint)new IPEndPoint(IPAddress.Parse(ip), port);                this.server.BeginSendTo(byteData, 0, byteData.Length, SocketFlags.None, iep, 
                 new AsyncCallback(this.AsyncSendCallback), this);            }            catch { }        }        /// <summary>        /// 异步发送数据的回调        /// </summary>        /// <param name="iar"></param>        private void AsyncSendCallback(IAsyncResult iar)        {            try            {                this.server.EndSendTo(iar);                iar.AsyncWaitHandle.Close();            }            catch            { }        }


            缓冲区数据处理函数:

        /// <summary>        /// 处理缓冲区中的数据        /// </summary>        /// <summary>        /// 处理缓冲区中的数据        /// </summary>        private void HandlerReceivedData()        {            while (this.serverStart)            {                lock (this.receivedBuffer)                {                    if (this.receivedBuffer.Count == 0) continue;                    BufferData buffer = this.receivedBuffer.Dequeue();                    if (this.iRceivedDataHandler != null) this.iRceivedDataHandler.ReceivedDataHandler(buffer);                }            }        }             

 

                数据处理线程组中的每个线程都会调用该函数,所以加个锁是必要的,对于数据的解析,给出了相应的数据接口,只要实现该接口即可实现其数据的处理,如向数据库存储,对数据的判断,向客户端回复等,都可以在该接口中去实现,因此具有一定的灵活性。

           数据接口很简单:

    

    public interface IDataHandler    {        /// <summary>        /// 数据处理接口        /// </summary>        /// <param name="buffer"></param>        void ReceivedDataHandler(BufferData buffer);    }

  

       对于该接口,朋友们可以自己根据需要进行扩展。

      

        指定客户端发送,广播,多播的实现:

       /// <summary>        /// 向指定客户端发送数据        /// </summary>        /// <param name="ip">客户端IP</param>        /// <param name="data">数据</param>        public void SendToClient(IPAddress ip, string data)        {            if (this.serverStart)            {                this.server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);                this.AsyncBeginSend(ip, data);            }        }        /// <summary>        /// 向指定客户端发送数据        /// </summary>        /// <param name="ip"></param>        /// <param name="data"></param>        public void SendToClient(string ip, string data)        {            this.SendToClient(IPAddress.Parse(ip), data);        }        /// <summary>        /// 向指定IP,指定端口的客户机发送数据        /// </summary>        /// <param name="ip">Ip地址</param>        /// <param name="port">端口号</param>        /// <param name="data">数据</param>        public void SendToClient(string ip, int port, string data)        {            if (this.serverStart)            {                this.server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);                this.AsyncBeginSend(ip, port, data);            }        }        /// <summary>        /// 广播        /// </summary>        /// <param name="data"></param>        public void Broadcast(string data)        {            this.SendToClient(this.brodcastIp, data);        }        /// <summary>        /// 在指定端口上广播数据        /// </summary>        /// <param name="data">数据</param>        /// <param name="port">端口号</param>        public void Broadcast(string data,int port)        {            this.SendToClient(this.brodcastIp, port, data);        }        /// <summary>        /// 多路广播        /// </summary>        /// <param name="ipAddress"></param>        public void Multicast(string data)        {            if (this.serverStart)            {                this.server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);                this.AsyncBeginSend(IPAddress.Broadcast, data);            }        }        /// <summary>        /// 指定端口进行多路广播        /// </summary>        /// <param name="data"></param>        /// <param name="port"></param>        public void Multicast(string data, int port)        {            if (this.serverStart)            {                this.server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);                this.AsyncBeginSend(IPAddress.Broadcast.ToString(), port, data);            }        }

 

        希望以上代码会对有需要的朋友有些帮助,也希望和大家一起共同进步,呵呵,加油!得意奋斗 源代码稍候会在我的下载资源http://download.csdn.net/detail/wdx888中给出。

      

原创粉丝点击