C#实现Socket异步通信,及完整源码库

C#实现Socket异步通信,及完整源码库

背景

工控上位机系统开发过程中不可避免的会用到socket通信技术,但是在支持多客户端并发连接时,常规方法效率很低。提高通信效率的一种途径就是使用Socket的异步通信,最开始从网上查了些资料,并进行整理。如果服务端使用异步通信,客户端使用常规同步通信(SocketTool.exe进行测试),没有什么问题。这个测试版本大概是在7年前写的,而且放到现场已经用了很多年。最近把Socket客户端也改为了异步通信,却发现最初写的服务端代码还是有问题。今天反复测试,最终修复bug。现把最新整理的完整通讯类库源码共享给大家。

关键代码

因为类库依赖了插件库ICSharp.Core.dll,请把代码中进行日志输出的部分,改为Console.WriteLine()输出,
实际把ICSharpCode.Core.LoggingService.Error换成Console.WriteLine
TcpService.cs

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

namespace Mesnac.Communication
{
    public class TcpService
    {
        private static TcpService instance = null;
        private SocketListener listener = null;
        private int maxConnection = 100;            //允许的最大连接数
        private int bufferSize = 1024 * 1024;       //接收缓冲区的大小
        private int port = 3666;                    //监听的端口号
        //private string ip = "127.0.0.1";            //监听的IP地址
        private TcpService()
        {
            try
            {
                object oMaxConnection = ConfigurationManager.AppSettings["MaxConnection"];
                if (oMaxConnection != null)
                {
                    int.TryParse(oMaxConnection.ToString(), out this.maxConnection);
                }
                object oPort = ConfigurationManager.AppSettings["Port"];
                if (oPort != null)
                {
                    int.TryParse(oPort.ToString(), out this.port);
                }
                
                ICSharpCode.Core.LoggingService<TcpService>.Debug("最大连接数:" + this.maxConnection);
                ICSharpCode.Core.LoggingService<TcpService>.Debug("侦听的端口号:" + this.port);
                this.listener = new SocketListener(this.maxConnection, this.bufferSize, this.GetIDByIP);
                this.listener.StartListenThread += new SocketListener.StartListenHandler(listener_StartListenThread);
                this.listener.ProcessAcceptComplete += new EventHandler<SocketAsyncEventArgs>(listener_ProcessAcceptComplete);
                this.listener.OnSended += new SocketListener.SendCompletedHandler(listener_OnSended);
                this.listener.OnMsgReceived += new SocketListener.ReceiveMsgHandler(listener_OnMsgReceived);
                this.listener.OnClientClose += new SocketListener.ClientClose(listener_OnClientClose);
                this.listener.Init();
                try
                {
                    this.listener.Start(this.port);
                }
                catch(System.Net.Sockets.SocketException se)
                {
                    if (se.SocketErrorCode == System.Net.Sockets.SocketError.AddressAlreadyInUse)
                    {
                        ICSharpCode.Core.LoggingService<TcpService>.Error(String.Format("端口号{0}已被占用!", this.port));
                    }
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<TcpService>.Error(ex.Message);
                ICSharpCode.Core.LoggingService<TcpService>.Error(ex.StackTrace);
            }
        }

        /// <summary>
        /// 处理客户端连接完成事件
        /// </summary>
        /// <param name="sender">客户端ip</param>
        /// <param name="e"></param>
        private void listener_ProcessAcceptComplete(object sender, SocketAsyncEventArgs e)
        {
            //触发处理客户端连接完成事件
            if (this.ProcessAcceptComplete != null)
            {
                this.ProcessAcceptComplete(sender, e);
            }
        }

        private void listener_OnMsgReceived(string uid, string info)
        {
            if (this.ReceiveMsgHandler != null)
            {
                this.ReceiveMsgHandler(uid, info);
            }
            ICSharpCode.Core.LoggingService<TcpService>.Debug(String.Format("接收到{0}发送的消息:{1}", uid, info));
        }

        private void listener_OnSended(string uid, string exception)
        {
            if (exception == "100")
            {
                ICSharpCode.Core.LoggingService<TcpService>.Debug(String.Format("已发送消息到{0}", uid));
            }
            else
            {
                //ICSharpCode.Core.LoggingService.Error(String.Format("消息发送错误:{0}", exception));
                ICSharpCode.Core.LoggingService<TcpService>.Warn("消息发送错误:客户端已经断开连接!");
            }
        }

        /// <summary>
        /// 客户端断开连接的事件处理程序
        /// </summary>
        /// <param name="uid"></param>
        private void listener_OnClientClose(string uid)
        {
            ICSharpCode.Core.LoggingService<TcpService>.Debug(String.Format("{0}:断开了连接...{1:yyyy-MM-dd HH:mm:ss}", uid, DateTime.Now));
        }

        private void listener_StartListenThread()
        {
            ICSharpCode.Core.LoggingService<TcpService>.Debug("开始侦听...");
            ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartListenCallBack), true);
        }

        private void StartListenCallBack(object listenFlag)
        {
            this.listener.ListenFlag = Convert.ToBoolean(listenFlag);
            this.listener.Listen();
        }
        /// <summary>
        /// 获取侦听的服务器IP地址
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        private string GetIDByIP(string ip)
        {
            return ip;
        }

        /// <summary>
        /// TCP通信服务实例
        /// </summary>
        public static TcpService Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new TcpService();
                }
                return instance;
            }
        }
        /// <summary>
        /// 启动服务
        /// </summary>
        public static void StartService()
        {
            if (instance == null)
            {
                instance = new TcpService();
            }
        }
        /// <summary>
        /// 重启服务
        /// </summary>
        public static void ReStartService()
        {
            StopService();
            StartService();
        }
        /// <summary>
        /// 停止服务
        /// </summary>
        public static void StopService()
        {
            if (instance != null)
            {
                try
                {
                    instance.listener.Stop();
                }
                catch (Exception ex)
                {
                    ICSharpCode.Core.LoggingService<TcpService>.Error("停止Socket侦听失败:" + ex.Message);
                }
                finally
                {
                    instance = null;
                }
            }
        }
        /// <summary>
        /// 发送消息至所有连接至本服务器的客户端计算机
        /// </summary>
        /// <param name="msg">消息内容</param>
        public void NetSendMsg(string msg)
        {
            foreach (string uid in this.listener.OnlineUID)
            {
                this.listener.Send(uid, msg);
            }
        }
        /// <summary>
        /// 发送消息至指定计算机
        /// </summary>
        /// <param name="uid">计算机IP地址</param>
        /// <param name="msg">消息内容</param>
        public void NetSendMsg(string uid, string msg)
        {
            this.listener.Send(uid, msg);
        }

        /// <summary>
        /// 接收到信息时触发的事件
        /// </summary>
        public event SocketListener.ReceiveMsgHandler ReceiveMsgHandler;
        /// <summary>
        /// 处理接收客户端连接完成事件
        /// </summary>
        public event EventHandler<SocketAsyncEventArgs> ProcessAcceptComplete;
    }
}

SocketListener.cs

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

namespace Mesnac.Communication
{
    public sealed class SocketListener : IDisposable
    {
        /// <summary>
        /// 缓冲区
        /// </summary>
        private BufferManager bufferManager;
        /// <summary>
        /// 服务器端Socket
        /// </summary>
        private Socket listenSocket;
        /// <summary>
        /// 服务同步锁
        /// </summary>
        private Mutex mutex;
        /// <summary>
        /// 当前连接数
        /// </summary>
        private Int32 numConnections;
        /// <summary>
        /// 最大并发量
        /// </summary>
        private Int32 numConcurrence;
        /// <summary>
        /// 服务器状态
        /// </summary>
        private ServerState serverstate;
        /// <summary>
        /// 读取写入字节
        /// </summary>
        private const Int32 opsToPreAlloc = 1;
        /// <summary>
        /// Socket连接池
        /// </summary>
        private SocketAsyncEventArgsPool readWritePool;
        /// <summary>
        /// 并发控制信号量
        /// </summary>
        private Semaphore semaphoreAcceptedClients;
        /// <summary>
        /// 通信协议
        /// </summary>
        private RequestHandler handler;
        /// <summary>
        /// 回调委托
        /// </summary>
        /// <param name="IP"></param>
        /// <returns></returns>
        public delegate string GetIDByIPFun(string IP);
        /// <summary>
        /// 回调方法实例
        /// </summary>
        private GetIDByIPFun GetIDByIP;
        /// <summary>
        /// 接收到信息时的事件委托
        /// </summary>
        /// <param name="info"></param>
        public delegate void ReceiveMsgHandler(string uid, string info);
        /// <summary>
        /// 接收到信息时的事件
        /// </summary>
        public event ReceiveMsgHandler OnMsgReceived;
        /// <summary>
        /// 客户端关闭连接时的委托
        /// </summary>
        /// <param name="uid"></param>
        public delegate void ClientClose(string uid);
        /// <summary>
        /// 客户端关闭连接时的事件
        /// </summary>
        public event ClientClose OnClientClose;
        /// <summary>
        /// 开始监听数据的委托
        /// </summary>
        public delegate void StartListenHandler();
        /// <summary>
        /// 开始监听数据的事件
        /// </summary>
        public event StartListenHandler StartListenThread;
        /// <summary>
        /// 发送信息完成后的委托
        /// </summary>
        /// <param name="successorfalse"></param>
        public delegate void SendCompletedHandler(string uid, string exception);
        /// <summary>
        /// 发送信息完成后的事件
        /// </summary>
        public event SendCompletedHandler OnSended;

        private bool listenFlag = false;

        public bool ListenFlag { get { return this.listenFlag; } set { this.listenFlag= value; } }

        /// <summary>
        /// 获取当前的并发数
        /// </summary>
        public Int32 NumConnections
        {
            get { return this.numConnections; }
        }
        /// <summary>
        /// 最大并发数
        /// </summary>
        public Int32 MaxConcurrence
        {
            get { return this.numConcurrence; }
        }
        /// <summary>
        /// 返回服务器状态
        /// </summary>
        public ServerState State
        {
            get
            {
                return serverstate;
            }
        }
        /// <summary>
        /// 获取当前在线用户的UID
        /// </summary>
        public string[] OnlineUID
        {
            get { return readWritePool.OnlineUID; }
        }

        /// <summary>
        /// 初始化服务器端
        /// </summary>
        /// <param name="numConcurrence">并发的连接数量(1000以上)</param>
        /// <param name="receiveBufferSize">每一个收发缓冲区的大小(32768)</param>
        public SocketListener(Int32 numConcurrence, Int32 receiveBufferSize, GetIDByIPFun GetIDByIP)
        {
            try
            {
                this.mutex = new Mutex();

                serverstate = ServerState.Initialing;
                this.numConnections = 0;
                this.numConcurrence = numConcurrence;
                this.bufferManager = new BufferManager(receiveBufferSize * numConcurrence * opsToPreAlloc, receiveBufferSize);
                this.readWritePool = new SocketAsyncEventArgsPool(numConcurrence);
                this.semaphoreAcceptedClients = new Semaphore(numConcurrence, numConcurrence);
                handler = new RequestHandler();
                this.GetIDByIP = GetIDByIP;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListener错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }

        /// <summary>
        /// 服务端初始化
        /// </summary>
        public void Init()
        {
            try
            {
                this.bufferManager.InitBuffer();
                SocketAsyncEventArgsWithId readWriteEventArgWithId;
                for (Int32 i = 0; i < this.numConcurrence; i++)
                {
                    readWriteEventArgWithId = new SocketAsyncEventArgsWithId();

                    readWriteEventArgWithId.SendSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
                    readWriteEventArgWithId.ReceiveSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceiveCompleted);
                    //只给接收的SocketAsyncEventArgs设置缓冲区
                    this.bufferManager.SetBuffer(readWriteEventArgWithId.ReceiveSAEA);
                    this.readWritePool.Push(readWriteEventArgWithId);
                }
                serverstate = ServerState.Inited;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("ScoketListner Init错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }

        /// <summary>
        /// 启动服务器
        /// </summary>
        /// <param name="data">端口号</param>
        public void Start(Object data)
        {
            try
            {
                Int32 port = (Int32)data;
                IPAddress[] addresslist = Dns.GetHostEntry(Environment.MachineName).AddressList;
                IPAddress ipAddress = addresslist[addresslist.Length - 1];
                object listenServerIP = ConfigurationManager.AppSettings["ListenServerIP"];
                if (listenServerIP != null)
                {
                    IPAddress.TryParse(listenServerIP.ToString(), out ipAddress); 
                }                           
                IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
                this.listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    this.listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
                    this.listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
                }
                else
                {
                    this.listenSocket.Bind(localEndPoint);
                }
                this.listenSocket.Listen(100);
                this.StartAccept(null);
                //开始监听已连接用户的发送数据
                if (StartListenThread != null)
                {
                    StartListenThread();
                }
                serverstate = ServerState.Running;

                mutex.WaitOne();
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListner Start错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }

        /// <summary>
        /// 开始监听线程的入口函数
        /// </summary>
        public void Listen()
        {

            while (this.listenFlag)
            {
                lock (readWritePool)
                {
                    string currUser = String.Empty;
                    try
                    {
                        string[] keys = readWritePool.OnlineUID;
                        foreach (string uid in keys)
                        {
                            currUser = uid;

                            if (uid != null && readWritePool.BusyPool.ContainsKey(uid) && readWritePool.BusyPool[uid] != null)
                            {
                                SocketAsyncEventArgsWithId sawd = readWritePool.BusyPool[uid];
                                if (sawd != null || sawd.ReceiveSAEA == null)
                                {
                                    if (readWritePool.BusyPool[uid].ReceiveSAEA.UID == null)
                                    {
                                        readWritePool.BusyPool[uid].ReceiveSAEA.UID = uid;
                                    }
                                    if ((readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).Available > 0)// readWritePool.BusyPool[uid].ReceiveSAEA.LastOperation != SocketAsyncOperation.Receive)
                                    {
                                        Boolean willRaiseEvent = (readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.BusyPool[uid].ReceiveSAEA);
                                        if (!willRaiseEvent)
                                            ProcessReceive(readWritePool.BusyPool[uid].ReceiveSAEA);
                                    }
                                }
                                else
                                {
                                    readWritePool.BusyPool.Remove(uid);
                                }
                                #region 注释
                                //else if (readWritePool.BusyPool[uid].ReceiveSAEA.LastOperation == SocketAsyncOperation.None)
                                //{
                                //    //以下为心跳处理
                                //    Boolean willRaiseEvent = (readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.BusyPool[uid].ReceiveSAEA);
                                //}
                                //else if (readWritePool.BusyPool[uid].ReceiveSAEA.LastOperation == SocketAsyncOperation.Receive && readWritePool.BusyPool[uid].ReceiveSAEA.SocketError == SocketError.Success)
                                //{
                                //    try
                                //    {
                                //        try
                                //        {
                                //            lock (String.Empty)
                                //            {
                                //                if (readWritePool.BusyPool[uid].IsAllowReceive)
                                //                {
                                //                    //以下为心跳处理
                                //                    Boolean willRaiseEvent = (readWritePool.BusyPool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.BusyPool[uid].ReceiveSAEA);
                                //                }
                                //            }
                                //        }
                                //        catch (System.InvalidOperationException ex)
                                //        {
                                //            //ICSharpCode.Core.LoggingService.Error("心跳处理报错无效操作:" + ex.Message);
                                //            //如果产生无效操作异常,说明正常连接,正在接收数据,停止心跳包发送数据
                                //            if (readWritePool.BusyPool.ContainsKey(uid))
                                //            {
                                //                readWritePool.BusyPool[uid].IsAllowReceive = false;
                                //            }
                                //        }
                                //    }
                                //    catch (Exception ex)
                                //    {
                                //        ICSharpCode.Core.LoggingService.Error("心跳处理报错:" + ex.Message);
                                //        ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
                                //        if (readWritePool.BusyPool.ContainsKey(uid))
                                //        {
                                //            readWritePool.BusyPool[uid].IsAllowReceive = false;
                                //        }
                                //    }
                                //}
                                #endregion
                            }

                        }

                    }
                    catch (Exception ex)
                    {
                        ICSharpCode.Core.LoggingService<SocketListener>.Error("监听错误:" + ex.Message, ex);
                        //ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
                        try
                        {
                            if (readWritePool.BusyPool.ContainsKey(currUser) && readWritePool.BusyPool[currUser] != null)
                            {
                                readWritePool.BusyPool[currUser].Dispose();
                                readWritePool.BusyPool.Remove(currUser);
                            }
                            else
                            {
                                readWritePool.BusyPool.Remove(currUser);
                            }
                            Interlocked.Decrement(ref this.numConnections);
                            ICSharpCode.Core.LoggingService<SocketListener>.Debug("当前连接数:" + this.numConnections);
                        }
                        catch { }
                    }
                }
                Thread.Sleep(1000);
            }
        }

        /// <summary>
        /// 发送信息
        /// </summary>
        /// <param name="uid">要发送的用户的uid</param>
        /// <param name="msg">消息体</param>
        public void Send(string uid, string msg)
        {
            try
            {

                if (uid == string.Empty || uid == "" || msg == string.Empty || msg == "")
                    return;
                SocketAsyncEventArgsWithId socketWithId = readWritePool.FindByUID(uid);
                if (socketWithId == null)
                    //说明用户已经断开  
                    //100   发送成功
                    //200   发送失败
                    //300   用户不在线
                    //其它  表示异常的信息
                    OnSended(uid, "300");
                else
                {
                    MySocketAsyncEventArgs e = socketWithId.SendSAEA;
                    if (e.SocketError == SocketError.Success)
                    {
                        int i = 0;
                        try
                        {
                            lock (String.Empty)
                            {
                                //string message = @"[lenght=" + msg.Length + @"]" + msg;
                                string message = msg;
                                byte[] sendbuffer = System.Text.Encoding.Default.GetBytes(message);
                                //e.SetBuffer(sendbuffer, 0, sendbuffer.Length);
                                (e.UserToken as Socket).Send(sendbuffer);
                                //Boolean willRaiseEvent = (e.UserToken as Socket).SendAsync(e);
                                //if (!willRaiseEvent)
                                //{
                                //    this.ProcessSend(e);
                                //}
                            }
                        }
                        catch (Exception ex)
                        {
                            //ICSharpCode.Core.LoggingService.Error("Send错误:" + ex.Message, ex);
                            //if (i <= 5)
                            //{
                            //    i++;
                            //    //如果发送出现异常就延迟0.01秒再发
                            //    Thread.Sleep(10);
                            //    Send(uid, msg);
                            //}
                            //else
                            //{
                            //    OnSended(uid, ex.ToString());
                            //}
                            OnSended(uid, ex.ToString());
                            this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
                        }
                    }
                    else
                    {
                        OnSended(uid, "200");
                        this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
                    }
                }

            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("Send错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }

        /// <summary>
        /// 停止服务器
        /// </summary>
        public void Stop()
        {
            try
            {
                this.listenFlag = false;
                if (listenSocket != null)
                    listenSocket.Close();
                listenSocket = null;
                Dispose();
                try
                {
                    mutex.ReleaseMutex();
                }
                catch (ApplicationException ae)
                {
                    ICSharpCode.Core.LoggingService<SocketListener>.Error(ae.Message);
                }
                serverstate = ServerState.Stoped;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListner Stop错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }


        private void StartAccept(SocketAsyncEventArgs acceptEventArg)
        {
            try
            {
                if (acceptEventArg == null)
                {
                    acceptEventArg = new SocketAsyncEventArgs();
                    acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
                }
                else
                    acceptEventArg.AcceptSocket = null;
                this.semaphoreAcceptedClients.WaitOne();
                Boolean willRaiseEvent = this.listenSocket.AcceptAsync(acceptEventArg);
                if (!willRaiseEvent)
                {
                    this.ProcessAccept(acceptEventArg);
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("SocketListener StartAccept错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }
        private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
        {
            this.ProcessAccept(e);
        }
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            lock (readWritePool)
            {
                try
                {
                    if (e.LastOperation != SocketAsyncOperation.Accept)    //检查上一次操作是否是Accept,不是就返回
                        return;
                    if (this.State == ServerState.Stoped) return;
                    if (e.AcceptSocket.RemoteEndPoint == null)  //服务器断开连接
                        return;
                    IPEndPoint ipEndPoint = e.AcceptSocket.RemoteEndPoint as IPEndPoint;
                    string UID = GetIDByIP(ipEndPoint.Address.ToString() + ":" + ipEndPoint.Port);   //根据IP获取用户的UID
                    if (UID == string.Empty || UID == null || UID == "")
                        return;
                    if (readWritePool.BusyPoolContains(UID))    //判断现在的用户是否已经连接,避免同一用户开两个连接
                    {
                        this.CloseClientSocket(UID);
                        return;
                    }
                    SocketAsyncEventArgsWithId readEventArgsWithId = this.readWritePool.Pop(UID);

                    if (readEventArgsWithId.ReceiveSAEA.SocketError != SocketError.Success && readEventArgsWithId.ReceiveSAEA.SocketError != SocketError.ConnectionReset)
                    {
                        readEventArgsWithId.ReceiveSAEA.UserToken = null;
                        readEventArgsWithId.ReceiveSAEA.Dispose();
                        readEventArgsWithId.ReceiveSAEA = new MySocketAsyncEventArgs("Receive");
                        readEventArgsWithId.ReceiveSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceiveCompleted);

                    }
                    if (readEventArgsWithId.SendSAEA.SocketError != SocketError.Success && readEventArgsWithId.SendSAEA.SocketError != SocketError.ConnectionReset)
                    {
                        readEventArgsWithId.SendSAEA.UserToken = null;
                        readEventArgsWithId.SendSAEA.Dispose();
                        readEventArgsWithId.SendSAEA = new MySocketAsyncEventArgs("Send");
                        readEventArgsWithId.SendSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
                    }

                    readEventArgsWithId.ReceiveSAEA.UserToken = e.AcceptSocket;
                    readEventArgsWithId.SendSAEA.UserToken = e.AcceptSocket;
                    readEventArgsWithId.IsAllowReceive = true;
                    Interlocked.Increment(ref this.numConnections);
                    //Console.WriteLine("当前连接:" + this.numConnections);
                    ICSharpCode.Core.LoggingService<SocketListener>.Debug("当前连接数:" + this.numConnections);
                    //触发处理客户端连接完成事件
                    if (this.ProcessAcceptComplete != null)
                    {
                        this.ProcessAcceptComplete(UID, e);
                    }
                    this.StartAccept(e);
                }
                catch (Exception ex)
                {
                    ICSharpCode.Core.LoggingService<SocketListener>.Error("ProcessAccept错误:" + ex.Message, ex);
                    ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
                }
            }
        }

        private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e)
        {
            ProcessReceive(e);
        }
        private void OnSendCompleted(object sender, SocketAsyncEventArgs e)
        {
            //ICSharpCode.Core.LoggingService.Debug("操作类型:" + e.LastOperation);
            ProcessSend(e);
        }
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            try
            {
                lock (String.Empty)
                {
                    if (e.LastOperation != SocketAsyncOperation.Receive)
                        return;
                    // 检查如果远程主机关闭了连接
                    if (e.BytesTransferred > 0)
                    {
                        if (e.SocketError == SocketError.Success)
                        {
                            Int32 byteTransferred = e.BytesTransferred;
                            string received = System.Text.Encoding.Default.GetString(e.Buffer, e.Offset, byteTransferred);
                            OnMsgReceived(((MySocketAsyncEventArgs)e).UID, received);
                            //检查消息的准确性
                            //string[] msg = handler.GetActualString(received);
                            //foreach (string m in msg)
                            //    OnMsgReceived(((MySocketAsyncEventArgs)e).UID, m);
                            try
                            {
                                //可以在这里设一个停顿来实现间隔时间段监听,这里的停顿是单个用户间的监听间隔
                                //发送一个异步接受请求,并获取请求是否为成功
                                Boolean willRaiseEvent = (e.UserToken as Socket).ReceiveAsync(e);
                                if (!willRaiseEvent)
                                    ProcessReceive(e);
                            }
                            catch (System.InvalidOperationException ex)
                            {
                                //ProcessReceive(e);
                            }
                        }
                    }
                    else
                        this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("ProcessReceive错误:" + ex.Message, ex);
                //ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }
        private void ProcessSend(SocketAsyncEventArgs e)
        {
            try
            {
                // 检查如果远程主机关闭了连接
                if (e.SocketError == SocketError.Success)
                {
                    if (e.LastOperation != SocketAsyncOperation.Send)
                        return;
                    if (e.BytesTransferred > 0)
                    {
                        if (e.SocketError == SocketError.Success)
                            OnSended(((MySocketAsyncEventArgs)e).UID, "100");
                        else
                            OnSended(((MySocketAsyncEventArgs)e).UID, "200");
                    }
                }
                else
                {
                    this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("ProcessSend错误:" + ex.Message, ex);
                //ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }

        private void CloseClientSocket(string uid)
        {
            try
            {
                if (uid == string.Empty || uid == "")
                    return;
                SocketAsyncEventArgsWithId saeaw = readWritePool.FindByUID(uid);
                if (saeaw == null)
                    return;
                Socket s = saeaw.ReceiveSAEA.UserToken as Socket;
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                    saeaw.ReceiveSAEA.DisconnectReuseSocket = true;
                }
                catch (Exception)
                {
                    //客户端已经关闭
                    //Console.WriteLine("客户端已经关闭!");
                    ICSharpCode.Core.LoggingService<SocketListener>.Warn("客户端已经关闭!");
                }
                this.semaphoreAcceptedClients.Release();
                Interlocked.Decrement(ref this.numConnections);
                this.readWritePool.Push(saeaw);
                //出发事件
                if (this.OnClientClose != null)
                {
                    this.OnClientClose(uid);
                }
                //Console.WriteLine("当前连接数:" + this.numConnections);
                ICSharpCode.Core.LoggingService<SocketListener>.Debug("当前连接数:" + this.numConnections);
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("CloseClientSocket错误:" + ex.Message, ex);
                //ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            try
            {
                if (bufferManager != null)
                {
                    bufferManager.Dispose();
                    bufferManager = null;
                }
                if (readWritePool != null)
                {
                    readWritePool.Dispose();
                    readWritePool = null;
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketListener>.Error("Dispose错误:" + ex.Message, ex);
                ICSharpCode.Core.LoggingService<SocketListener>.Error(ex.StackTrace);
            }
        }

        #endregion

        /// <summary>
        /// 处理接收客户端连接完成事件
        /// </summary>
        public event EventHandler<SocketAsyncEventArgs> ProcessAcceptComplete;
    }
}

SocketClient.cs

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

namespace Mesnac.Communication
{
    /// <summary>
    /// Socket客户端类,连接App.Config中FeedingIP:Port
    /// </summary>
    public class SocketClient : IDisposable
    {
        #region 字段、委托、事件

        private static SocketClient instance = null;
        /// <summary>
        /// 客户端连接Socket
        /// </summary>
        private Socket clientSocket;
        /// <summary>
        /// 连接状态
        /// </summary>
        private Boolean connected = false;
        /// <summary>
        /// 连接点
        /// </summary>
        private IPEndPoint hostEndPoint;
        /// <summary>
        /// 连接信号量
        /// </summary>
        private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
        /// <summary>
        /// 接受到数据时的委托
        /// </summary>
        /// <param name="info"></param>
        public delegate void ReceiveMsgHandler(string info);
        /// <summary>
        /// 接收到数据时调用的事件
        /// </summary>
        public event ReceiveMsgHandler OnMsgReceived;
        /// <summary>
        /// 开始监听数据的委托
        /// </summary>
        public delegate void StartListenHandler();
        /// <summary>
        /// 开始监听数据的事件
        /// </summary>
        public event StartListenHandler StartListenThread;
        /// <summary>
        /// 发送信息完成的委托
        /// </summary>
        /// <param name="successorfalse"></param>
        public delegate void SendCompleted(bool successorfalse);
        /// <summary>
        /// 发送信息完成的事件
        /// </summary>
        public event SendCompleted OnSended;
        /// <summary>
        /// 监听接收的SocketAsyncEventArgs
        /// </summary>
        private SocketAsyncEventArgs listenerSocketAsyncEventArgs;
        /// <summary>
        /// 心跳时钟
        /// </summary>
        private System.Timers.Timer _timer = null;
        /// <summary>
        /// SocketServer服务器IP
        /// </summary>
        public static string hostName;
        /// <summary>
        /// SocketServer服务器端口号
        /// </summary>
        public static int port;

        #endregion

        #region 属性定义

        /// <summary>
        /// SocketServer服务器IP地址
        /// </summary>
        public static string ServerIp
        {
            get
            {
                return ConfigurationManager.AppSettings["ServerIp"];
            }
        }
        /// <summary>
        /// SocketServer服务器端口号
        /// </summary>
        public static string ServerPort
        {
            get
            {
                return ConfigurationManager.AppSettings["Port"];
            }
        }
        /// <summary>
        /// 是否处于连接状态,需要通过定时发送心跳信息来驱动连接状态的变化
        /// </summary>
        public bool IsConnected
        {
            get
            {
                if (this.clientSocket == null)
                {
                    return false;
                }
                return this.clientSocket.Connected;
            }
        }


        /// <summary>
        /// TCP通信服务实例
        /// </summary>
        public static SocketClient Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new SocketClient();
                }
                return instance;
            }
        }

        #endregion

        #region 初始化

        /// <summary>
        /// 启动服务
        /// </summary>
        public static void StartService()
        {
            if (instance == null)
            {
                instance = new SocketClient();
                instance.Connect();
            }
        }

        /// <summary>
        /// 初始化客户端
        /// </summary>
        /// <param name="hostName">服务端地址{IP地址}</param>
        /// <param name="port">端口号</param>
        public SocketClient()//String hostName, Int32 port
        {
            this.InitHostEndPoint();
        }
        /// <summary>
        /// 初始化HostEndPoint
        /// </summary>
        private void InitHostEndPoint()
        {
            string hostName = ServerIp;
            int port = 0;
            int.TryParse(ServerPort, out port);

            IPAddress address = null;
            if (!String.IsNullOrEmpty(hostName))
            {
                IPAddress.TryParse(hostName, out address);
            }
            else
            {
                IPHostEntry host = Dns.GetHostEntry("127.0.0.1");
                IPAddress[] addressList = host.AddressList;
                foreach (IPAddress ad in addressList)
                {
                    if (ad.AddressFamily == AddressFamily.InterNetwork)
                    {
                        address = ad;
                        break;
                    }
                }
            }

            this.hostEndPoint = new IPEndPoint(address, port);
        }

        #endregion

        #region 连接

        /// <summary>
        /// 连接服务端
        /// </summary>
        public bool Connect()
        {
            bool result = false;
            this.Disconnect();
            this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
            connectArgs.UserToken = this.clientSocket;
            connectArgs.RemoteEndPoint = this.hostEndPoint;
            connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
            result = clientSocket.ConnectAsync(connectArgs);
            //等待连接结果
            //autoConnectEvent.WaitOne();
            SocketError errorCode = connectArgs.SocketError;
            if (errorCode == SocketError.Success)
            {
                listenerSocketAsyncEventArgs = new SocketAsyncEventArgs();
                byte[] receiveBuffer = new byte[32768];
                listenerSocketAsyncEventArgs.UserToken = clientSocket;
                listenerSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
                listenerSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                StartListenThread += new SocketClient.StartListenHandler(listener_StartListenThread);
                StartListenThread();
                return result;
            }
            else
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Warn(String.Format("连接SocketServer={0}:{1}失败", this.hostEndPoint.Address.ToString(), this.hostEndPoint.Port));
                //throw new SocketException((Int32)errorCode);
                connectArgs.Dispose();
                this.Dispose();
                return false;
            }
        }

        /// <summary>
        /// 重新连接
        /// </summary>
        /// <returns></returns>
        public bool ReConnect()
        {
            try
            {
                this.Dispose();
                bool result = this.Connect();
                if (result)
                {
                    this.Send("TestConnect");
                }
                return this.connected;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Error("网络断开:" + ex.Message, ex);
                return false;
            }
        }

        /// <summary>
        /// 没有连接对象返回false,否则重连
        /// </summary>
        /// <returns>返回重连结果</returns>
        public bool IsOrNoReConnect()
        {
            try
            {
                lock (this)
                {
                    if (this.clientSocket == null)
                    {
                        return false;
                    }

                    return this.ReConnect();
                }
            }
            catch (System.Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Error("网络已经断开:" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 连接的完成方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnConnect(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                //autoConnectEvent.Set();
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Error(ex.Message);
            }

            this.connected = (e.SocketError == SocketError.Success);
        }

        #endregion

        #region 断开连接

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            if (clientSocket != null)
            {
                if (clientSocket.Connected)
                {
                    //autoConnectEvent.Close();
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Disconnect(false);
                }
                StopListenThread();
                ICSharpCode.Core.LoggingService<SocketClient>.Debug("断开连接");
            }
        }

        #endregion

        #region 心跳

        #region 启动心跳时钟

        /// <summary>
        /// 启动定时器运行服务
        /// </summary>
        public void StartHeartbeat()
        {
            if (this._timer == null)
            {
                this._timer = new System.Timers.Timer();
                this._timer.Interval = 2000;
                this._timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
                this._timer.Start();
            }
        }

        #endregion

        #region 停止心跳时钟

        /// <summary>
        /// 停止定时器运行服务
        /// </summary>
        public void StopHeartbeat()
        {
            if (this._timer != null)
            {
                this._timer.Stop();
                this._timer.Dispose();
                this._timer = null;
            }
        }

        #endregion

        protected void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (this.connected)
            {
                this.Send("0000");      //发送心跳包
            }
            else
            {
                this.ReConnect();       //重新连接
            }
        }

        #endregion

        #region 侦听

        private void listener_StartListenThread()
        {
            ICSharpCode.Core.LoggingService<SocketClient>.Debug("开始侦听...");
            //receiveThread = new Thread(new ThreadStart(Listen));
            Listen();
        }

        /// <summary>
        /// 停止监听线程
        /// </summary>
        public void StopListenThread()
        {
            try
            {
                this.StopHeartbeat();
                if (StartListenThread != null)
                {
                    StartListenThread -= new SocketClient.StartListenHandler(listener_StartListenThread);
                }
                if (this.listenerSocketAsyncEventArgs != null)
                {
                    listenerSocketAsyncEventArgs.Completed -= new EventHandler<SocketAsyncEventArgs>(OnReceive);
                    this.listenerSocketAsyncEventArgs.UserToken = null;
                    this.listenerSocketAsyncEventArgs.Dispose();
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Error("停止监听线程异常:", ex);
            }
        }

        /// <summary>
        /// 开始监听线程的入口函数
        /// </summary>
        public void Listen()
        {
            try
            {
                Socket socket = listenerSocketAsyncEventArgs.UserToken as Socket;
                if (socket != null)
                {
                    socket.ReceiveAsync(listenerSocketAsyncEventArgs);
                    if (socket.Connected)
                    {
                        this.StartHeartbeat();
                    }
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Error("侦听异常!", ex);
            }
        }

        #endregion

        #region 消息

        /// <summary>
        /// 发送信息
        /// </summary>
        /// <param name="message"></param>
        public void Send(String message)
        {
            if (clientSocket != null && this.connected)
            {
                Byte[] sendBuffer = Encoding.Default.GetBytes(message);
                SocketAsyncEventArgs senderSocketAsyncEventArgs = new SocketAsyncEventArgs();
                senderSocketAsyncEventArgs.UserToken = this.clientSocket;
                senderSocketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
                senderSocketAsyncEventArgs.RemoteEndPoint = this.hostEndPoint;
                senderSocketAsyncEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
                clientSocket.SendAsync(senderSocketAsyncEventArgs);
            }
            else
            {
                //throw new SocketException((Int32)SocketError.NotConnected);
                ICSharpCode.Core.LoggingService<SocketClient>.Warn("Socket未初始化或未连接!");
            }
        }


        /// <summary>
        /// 接收的完成方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                if (e.BytesTransferred > 0)
                {
                    string msg = Encoding.Default.GetString(e.Buffer, 0, e.BytesTransferred);
                    ICSharpCode.Core.LoggingService<SocketClient>.Debug("接收到数据" + msg);
                    Listen();
                    if (OnMsgReceived != null)
                        OnMsgReceived(msg);
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<SocketClient>.Error("接收数据异常:" + ex.Message, ex);
            }
        }
        /// <summary>
        /// 发送的完成方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                //触发事件
                if (OnSended != null)
                {
                    OnSended(true);
                }
            }
            else
            {
                //触发事件
                if (OnSended != null)
                {
                    OnSended(false);
                }
                this.ProcessError(e);
            }
        }
        /// <summary>
        /// 处理错误
        /// </summary>
        /// <param name="e"></param>
        private void ProcessError(SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;
            if (s != null && s.Connected)
            {
                try
                {
                    s.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                    //client already closed
                }
                finally
                {
                    if (s.Connected)
                    {
                        s.Close();
                    }
                }
            }
            //throw new SocketException((Int32)e.SocketError);
        }

        #endregion

        #region IDisposable Members
        public void Dispose()
        {
            this.Disconnect();
            if (clientSocket != null)
            {
                this.clientSocket.Close();
                this.clientSocket.Dispose();
                this.clientSocket = null;
            }
        }
        #endregion
    }
}

完整源码下载

完整源码下载

猜你喜欢

转载自blog.csdn.net/zlbdmm/article/details/89360499