Udp 异步通信(三)

转自:https://blog.csdn.net/zhujunxxxxx/article/details/44258719

 

1)服务端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpSocketServer
{
    public class UdpServerAsync
    {
        #region Fields  

        private int _maxClient;

        private Socket _serverSock;

        private List<EndPoint> _clients;

        private bool disposed = false;

        private byte[] _recvBuffer;

        #endregion

        #region Properties  

        public bool IsRunning { get; private set; }

        public IPAddress Address { get; private set; }

        public int Port { get; private set; }

        public Encoding Encoding { get; set; }

        #endregion

        #region 构造函数  

        public UdpServerAsync(int listenPort)
            : this(IPAddress.Any, listenPort, 1024)
        {
        }

        public UdpServerAsync(IPEndPoint localEP)
            : this(localEP.Address, localEP.Port, 1024)
        {
        }

        public UdpServerAsync(IPAddress localIPAddress, int listenPort, int maxClient)
        {
            this.Address = localIPAddress;
            this.Port = listenPort;
            this.Encoding = Encoding.Default;

            _maxClient = maxClient;

            _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

            _recvBuffer = new byte[_serverSock.ReceiveBufferSize];
        }

        #endregion

        #region Method  

        public void Start()
        {
            if (!IsRunning)
            {
                IsRunning = true;
                _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                //_serverSock.Connect(new IPEndPoint(IPAddress.Any, 0));  

                SocketState so = new SocketState();
                so.buffer = new byte[_serverSock.ReceiveBufferSize];
                so.remote = new IPEndPoint(Address, Port);

                _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None,
                    ref so.remote, new AsyncCallback(ReceiveDataAsync), so);
            }
        }

        public void Stop()
        {
            if (IsRunning)
            {
                IsRunning = false;
                _serverSock.Close();                
            }
        }

        private void ReceiveDataAsync(IAsyncResult ar)
        {
            SocketState so = ar.AsyncState as SocketState;

            int len = -1;
            try
            {
                len = _serverSock.EndReceiveFrom(ar, ref so.remote);
                so.recvSize = len;
                //len = _serverSock.EndReceiveFrom(ar, ref sender);  

                //EndReceiveFrom 和 EndReceive区别  
                //len = _serverSock.EndReceive(ar);  
                //TODO 处理数据  

                //触发数据收到事件  
                RaiseDataReceived(so);
            }
            catch (Exception)
            {
                //TODO 处理异常  
                RaiseOtherException(so);
            }
            finally
            {
                if (IsRunning && _serverSock != null)
                    _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None,
                ref so.remote, new AsyncCallback(ReceiveDataAsync), so);
            }
        }

        public void Send(byte[] data, EndPoint remote)
        {
            try
            {
                RaisePrepareSend(null);
                _serverSock.BeginSendTo(data, 0, data.Length, SocketFlags.None, remote, new AsyncCallback(SendDataEnd), _serverSock);
            }
            catch (Exception)
            {
                //TODO 异常处理  
                RaiseOtherException(null);
            }
        }

        private void SendDataEnd(IAsyncResult ar)
        {
            ((Socket)ar.AsyncState).EndSendTo(ar);
            RaiseCompletedSend(null);
        }

        #endregion

        #region 事件  

        public event EventHandler<UDPMessage> DataReceived;

        private void RaiseDataReceived(SocketState state)
        {
            if (DataReceived != null)
            {
                DataReceived(this, new UDPMessage(state));
            }
        }

        /// <summary>  
        /// 发送数据前的事件  
        /// </summary>  
        public event EventHandler<UDPMessage> PrepareSend;

        /// <summary>  
        /// 触发发送数据前的事件  
        /// </summary>  
        /// <param name="state"></param>  
        private void RaisePrepareSend(SocketState state)
        {
            if (PrepareSend != null)
            {
                PrepareSend(this, new UDPMessage(state));
            }
        }

        /// <summary>  
        /// 数据发送完毕事件  
        /// </summary>  
        public event EventHandler<UDPMessage> CompletedSend;

        /// <summary>  
        /// 触发数据发送完毕的事件  
        /// </summary>  
        /// <param name="state"></param>  
        private void RaiseCompletedSend(SocketState state)
        {
            if (CompletedSend != null)
            {
                CompletedSend(this, new UDPMessage(state));
            }
        }

        /// <summary>  
        /// 网络错误事件  
        /// </summary>  
        public event EventHandler<UDPMessage> NetError;
        /// <summary>  
        /// 触发网络错误事件  
        /// </summary>  
        /// <param name="state"></param>  
        private void RaiseNetError(SocketState state)
        {
            if (NetError != null)
            {
                NetError(this, new UDPMessage(state));
            }
        }

        /// <summary>  
        /// 异常事件  
        /// </summary>  
        public event EventHandler<UDPMessage> OtherException;
        /// <summary>  
        /// 触发异常事件  
        /// </summary>  
        /// <param name="state"></param>  
        private void RaiseOtherException(SocketState state, string descrip)
        {
            if (OtherException != null)
            {
                OtherException(this, new UDPMessage(descrip, state));
            }
        }
        private void RaiseOtherException(SocketState state)
        {
            RaiseOtherException(state, "");
        }
        #endregion

        #region Close  
        /// <summary>  
        /// 关闭一个与客户端之间的会话  
        /// </summary>  
        /// <param name="state">需要关闭的客户端会话对象</param>  
        public void Close(SocketState state)
        {
            if (state != null)
            {
                //_clients.Remove(state);  
                //_clientCount--;  
                //TODO 触发关闭事件  
            }
        }
        /// <summary>  
        /// 关闭所有的客户端会话,与所有的客户端连接会断开  
        /// </summary>  
        public void CloseAllClient()
        {
            //foreach (AsyncUDPSocketState client in _clients)  
            //{  
            //    Close(client);  
            //}  
            //_clientCount = 0;  
            //_clients.Clear();  
        }

        #endregion

        #region 释放  
        /// <summary>  
        /// Performs application-defined tasks associated with freeing,   
        /// releasing, or resetting unmanaged resources.  
        /// </summary>  
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>  
        /// Releases unmanaged and - optionally - managed resources  
        /// </summary>  
        /// <param name="disposing"><c>true</c> to release   
        /// both managed and unmanaged resources; <c>false</c>   
        /// to release only unmanaged resources.</param>  
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    try
                    {
                        Stop();
                        if (_serverSock != null)
                        {
                            _serverSock = null;
                        }
                    }
                    catch (SocketException)
                    {
                        //TODO  
                        RaiseOtherException(null);
                    }
                }
                disposed = true;
            }
        }
        #endregion
    }
}

2)客户端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpSocketClient
{
    public class UDPClientAsync
    {
        #region 字段

        public Socket udpClient;

        public EndPoint endPoint;

        private SocketState state;

        #endregion

        #region 属性

        public IPAddress Address { get; private set; }  

        public int Port { get; private set; }

        #endregion

        #region 构造函数

        public UDPClientAsync(IPAddress ipAddress,int port)
        {
            this.Address = ipAddress;
            this.Port = port;
            endPoint = new IPEndPoint(Address, Port);
            udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        }

        public UDPClientAsync(IPEndPoint ipEndPoint)
            :this(ipEndPoint.Address,ipEndPoint.Port)
        {
        }

        #endregion

        #region Method

        public void Send(byte[] bytes)
        {
            udpClient.BeginSendTo(bytes, 0, bytes.Length, SocketFlags.None, endPoint, iAsyncResult=>
            {
                udpClient.EndSendTo(iAsyncResult);

                RaiseDataSend();
            }, null);
        }

        public void Receive()
        {
            state = new UdpSocketClient.SocketState();
            state.buffer = new byte[udpClient.ReceiveBufferSize];
            state.remote = new IPEndPoint(Address, Port);

            udpClient.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remote, 
                new AsyncCallback(DataReceivedCallBack), null);
        }

        private void DataReceivedCallBack(IAsyncResult iAsyncResult)
        {
            int len = -1;
            try
            {
                len = udpClient.EndReceiveFrom(iAsyncResult, ref state.remote);
                state.recvSize = len;

                RaiseDataReceived(state);
            }
            catch(Exception ex)
            {
                RaiseErrorException(ex.Message);
            }

            //if (udpClient != null)
            //{
            //    udpClient.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remote, 
            //        new AsyncCallback(DataReceivedCallBack), null);
            //}
        }

        public void Close()
        {
            udpClient.Shutdown(SocketShutdown.Both);

            udpClient.Close();
            GC.Collect();
        }

        #endregion

        #region 事件

        public event EventHandler<UDPMessage> DataReceived;

        private void RaiseDataReceived(SocketState state)
        {
            if(DataReceived!=null)
            {
                DataReceived(this, new UdpSocketClient.UDPMessage(state));
            }
        }

        public event EventHandler<UDPMessage> DataSend;

        private void RaiseDataSend()
        {
            if(DataSend!=null)
            {
                DataSend(this, null);
            }
        }

        public event EventHandler<UDPMessage> ErrorException;

        private void RaiseErrorException(string msg)
        {
            if(ErrorException!=null)
            {
                ErrorException(this, new UdpSocketClient.UDPMessage(msg));
            }
        }

        #endregion
    }
}

3)消息类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace UdpSocketServer
{
    public class SocketState
    {
        public Socket workSocket = null;

        public byte[] buffer;

        public int recvSize;

        public EndPoint remote;

        public string Diagram
        {
            get
            {
                byte[] data = new byte[recvSize];
                Array.ConstrainedCopy(buffer, 0, data, 0, recvSize);
                //_datagram = Encoding.Default.GetString(data);
                return Encoding.Default.GetString(data);
            }
        }
    }
}

4)服务端信息类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UdpSocketClient
{
    public class UDPMessage : EventArgs
    {
        /// <summary> 
        /// 提示信息 
        /// </summary> 
        public string _msg;
        /// <summary> 
        /// 客户端状态封装类 
        /// </summary> 
        public SocketState _state;
        /// <summary> 
        /// 是否已经处理过了 
        /// </summary> 
        public bool IsHandled { get; set; }
        public UDPMessage(string msg)
        {
            this._msg = msg;
            IsHandled = false;
        }
        public UDPMessage(SocketState state)
        {
            this._state = state;
            IsHandled = false;
        }
        public UDPMessage(string msg, SocketState state)
        {
            this._msg = msg;
            this._state = state;
            IsHandled = false;
        }
    }
}

 

posted @ 2018-06-20 17:45  81192  阅读(350)  评论(0编辑  收藏  举报