zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    }
  • 相关阅读:
    vs2017 vs2019 打开cs文件提示无法识别的GUID格式
    A股和B股票的区别?
    选股:“均线是水,K线是舟,量是马达!”的选美理念!
    什么是K线?K线的详解!
    5日均线MACD
    炒股的常见技术指标
    选股票几大原则:趋势原则,强势原则,分批原则
    金融蝴蝶效应
    股市里的大户和散户
    期货平仓/强制平仓/爆仓-股市平仓建仓
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/9205025.html
Copyright © 2011-2022 走看看