基于链表会话管理的TCP服务端实现

终于将完整的会话机制和消息过滤机制追加到了通用通信模型中,整个通信构建在通信工厂中,通过消息过滤器注入,实现消息的解析。

此处只处理了接收消息的解析,未将发送消息过滤器作为一部分直接插入,主要是考虑到写入时的灵活性,后期逐步追加。

首先是接口的定义,接口部分实现了基本的约束。

 /// <summary>
    /// 通信接口
    /// </summary>
    public interface ICommunication
    {
        /// <summary>
        /// 通信端口初始化
        /// </summary>
        /// <param name="communicationParamertes">通信端口初始化</param>
        void InitCommunication(CommunicationParamertercs communicationParamerters);
        /// <summary>
        /// 启动
        /// 如果打开失败,会自动尝试关闭掉
        /// </summary>
        void Open();
        /// <summary>
        /// 是否开启
        /// </summary>
        bool IsOpen { get; }
        /// <summary>
        /// 请求数据
        /// </summary>
        /// <param name="data"></param>
        void Request(string data);
        /// <summary>
        /// 请求数据
        /// </summary>
        /// <param name="data"></param>
        void Request(byte[] data);
        /// <summary>
        /// 异步请求数据,在其他线程上
        /// </summary>
        /// <param name="data"></param>
        void ASyncRequest(string data);
        /// <summary>
        /// 异步请求数据,在其他线程上
        /// </summary>
        /// <param name="data"></param>
        void ASyncRequest(byte[] data);
        /// <summary>
        /// 请求数据,根据会话ID发送,
        /// 一般用于并发处理场合,根据ID来确认具体的发送会话,
        /// 用于服务监听应答场合
        /// </summary>
        /// <param name="sessionID">会话ID</param>
        /// <param name="data">数据</param>
        void Request(Guid sessionID,string data);
        /// <summary>
        /// 请求数据,根据会话ID发送,
        /// 一般用于并发处理场合,根据ID来确认具体的发送会话
        /// 用于服务监听应答场合
        /// </summary>
        /// <param name="sessionID">会话ID</param>
        /// <param name="data">数据</param>
        void Request(Guid sessionID,byte[] data);
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        IResponseData RequestWait(string data, int timeOut = 500);
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="describe">请求描述</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        IResponseData RequestWait(string data, string describe, int timeOut = 500);
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        IResponseData RequestWait(byte[] data, int timeOut = 500);
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="describe">请求描述</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        IResponseData RequestWait(byte[] data,string describe, int timeOut = 500);
        /// <summary>
        /// 异步请求等待应答数据
        /// 异步线程上消息队列响应
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        void AsyncRequestWait(AsyncRequestWaitData<string> asyncRequestWaitData);

        /// <summary>
        /// 异步请求等待应答数据
        /// 异步线程上消息队列响应
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        /// <param name="describe">请求描述</param>
        void AsyncRequestWait(AsyncRequestWaitData<string> asyncRequestWaitData,string describe);
        /// <summary>
        /// 异步请求等待应答数据
        /// 异步线程上消息队列响应
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        void AsyncRequestWait(AsyncRequestWaitData<byte[]> asyncRequestWaitData);
        /// <summary>
        /// 异步请求等待应答数据
        /// 异步线程上消息队列响应
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        /// <param name="describe">请求描述</param>
        void AsyncRequestWait(AsyncRequestWaitData<byte[]> asyncRequestWaitData,string describe);
        /// <summary>
        /// 数据应答
        /// 异步线程上消息队列响应
        /// </summary>
        event ResponseHandler<IResponseData> OnResponseBuffer;
        /// <summary>
        /// 异常信息响应
        /// 异步线程上消息队列响应
        /// </summary>
        event ExceptionHandler<Exception> OnException;
        /// <summary>
        /// 普通信息通知
        /// 异步线程上消息队列响应
        /// </summary>
        event ExceptionHandler<string> OnInfo;
        /// <summary>
        /// 打开前触发
        /// </summary>
        event ResponseHandler<bool> OnOpening;
        /// <summary>
        /// 打开后触发
        /// </summary>
        event ResponseHandler<bool> OnOpened;
        /// <summary>
        /// 会话构建后触发
        /// </summary>
        event SessionHandler OnSessionAdded;
        /// <summary>
        /// 关闭前触发
        /// </summary>
        event ResponseHandler<bool> OnClosing;
        /// <summary>
        /// 关闭后触发
        /// </summary>
        event ResponseHandler<bool> OnClosed;
        /// <summary>
        /// 关闭
        /// </summary>
        void Close();
    }


抽象基类部分,将能实现的大部分通用业务逻辑进行抽象整合。

 

 /// <summary>
    /// 通信基类
    /// </summary>
    internal abstract class BaseCommunication:ICommunication
    {
        /// <summary>
        /// 通信端口初始化参数
        /// </summary>
        protected CommunicationParamertercs communicationParamerters;
        /// <summary>
        /// 响应处理消息队列,用于应答排队
        /// </summary>
        private IoCompletionMessageFIFO responseMessageFIFO = null;
        /// <summary>
        /// 启动
        /// 如果打开失败,会自动尝试关闭掉
        /// </summary>
        public abstract void Open();
        /// <summary>
        /// 是否开启
        /// </summary>
        public bool IsOpen
        {
            get
            {
                if (responseMessageFIFO == null)
                {
                    return false;
                }
                return responseMessageFIFO.IsOpened;
            }
        }
        /// <summary>
        /// 关闭
        /// </summary>
        public abstract void Close();
        /// <summary>
        /// 初始化设备通信端口参数
        /// </summary>
        /// <param name="communicationParamertes">设备通信端口初始化参数</param>
        public virtual void InitCommunication(CommunicationParamertercs communicationParamerters)
        {
            this.communicationParamerters = communicationParamerters;
        }

        #region 请求写入数据
        /// <summary>
        /// 请求写入字符串
        /// </summary>
        /// <param name="data"></param>
        public virtual void Request(string data)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求写入字节流
        /// </summary>
        /// <param name="data"></param>
        public virtual void Request(byte[] data)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 异步请求数据,在其他线程上
        /// </summary>
        /// <param name="data"></param>
        public virtual void ASyncRequest(string data)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 异步请求数据,在其他线程上
        /// </summary>
        /// <param name="data"></param>
        public virtual void ASyncRequest(byte[] data)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        public virtual IResponseData RequestWait(string data, int timeOut = 500)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        public virtual IResponseData RequestWait(byte[] data, int timeOut = 500)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 异步请求等待应答数据,一般用于批量请求
        /// 在回调中执行处理
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        public virtual void AsyncRequestWait(AsyncRequestWaitData<string> asyncRequestWaitData)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 异步请求等待应答数据,一般用于批量请求
        /// 在回调中执行处理
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        public virtual void AsyncRequestWait(AsyncRequestWaitData<byte[]> asyncRequestWaitData)
        {
            throw new Exception("不支持的调用");
        }

        /// <summary>
        /// 异步请求等待应答数据,一般用于批量请求
        /// 在回调中执行处理
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        /// <param name="describe">请求描述</param>
        public virtual void AsyncRequestWait(AsyncRequestWaitData<string> asyncRequestWaitData, string describe)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 异步请求等待应答数据,一般用于批量请求
        /// 在回调中执行处理
        /// </summary>
        /// <param name="asyncRequestWaitData">异步请求数据</param>
        /// <param name="describe">请求描述</param>
        public virtual void AsyncRequestWait(AsyncRequestWaitData<byte[]> asyncRequestWaitData, string describe)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="describe">请求描述</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        public virtual IResponseData RequestWait(string data, string describe, int timeOut = 500)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求等待应答数据
        /// </summary>
        /// <param name="data">请求数据</param>
        /// <param name="describe">请求描述</param>
        /// <param name="timeOut">请求超时时间,单位是毫秒</param>
        /// <returns>
        /// 返回响应数据
        /// </returns>
        public virtual IResponseData RequestWait(byte[] data, string describe, int timeOut = 500)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求数据,根据会话ID发送,
        /// 一般用于并发处理场合,根据ID来确认具体的发送会话
        /// 用于服务监听应答场合
        /// </summary>
        /// <param name="sessionID">会话ID</param>
        /// <param name="data">数据</param>
        public virtual void Request(Guid sessionID, string data)
        {
            throw new Exception("不支持的调用");
        }
        /// <summary>
        /// 请求数据,根据会话ID发送,
        /// 一般用于并发处理场合,根据ID来确认具体的发送会话
        /// 用于服务监听应答场合
        /// </summary>
        /// <param name="sessionID">会话ID</param>
        /// <param name="data">数据</param>
        public virtual void Request(Guid sessionID, byte[] data)
        {
            throw new Exception("不支持的调用");
        }
        #endregion
        /// <summary>
        /// 压入数据
        /// </summary>
        /// <param name="obj"></param>
        protected virtual void Post(object obj)
        {
            if (responseMessageFIFO != null && responseMessageFIFO.IsOpened == true)
            {
                responseMessageFIFO.Post(obj);
            }
            else
            {
                if (obj is Exception)
                {
                    if (OnException != null)
                    {
                        OnException(this, (Exception)obj);
                    }
                }
                else if (obj is string)
                {
                    if (OnInfo != null)
                    {
                        OnInfo(this, (string)obj);
                    }
                }
            }
        }
        /// <summary>
        /// 并发式处理
        /// </summary>
        protected virtual void ParallelPost(object obj)
        {
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(responseMessageFIFO_Exceute), obj);
        }
        /// <summary>
        /// 回调处理数据
        /// </summary>
        /// <param name="obj"></param>
        void responseMessageFIFO_Exceute(object obj)
        {
            if (obj is Exception)
            {
                if (OnException != null)
                {
                    OnException(this, (Exception)obj);
                }
            }
            else if (obj is IResponseData)
            {
                if (OnResponseBuffer != null)
                {
                    OnResponseBuffer(this, (IResponseData)obj);
                }
            }
            else if (obj is string)
            {
                if (OnInfo != null)
                {
                    OnInfo(this, (string)obj);
                }
            }
        }
        /// <summary>
        /// 响应消息队列启动
        /// </summary>
        protected virtual void OpenRespnoseMessageFIFO()
        {
            if (responseMessageFIFO == null)
            {
                responseMessageFIFO = new IoCompletionMessageFIFO();
                responseMessageFIFO.Exceute += responseMessageFIFO_Exceute;
            }
            if (responseMessageFIFO != null && responseMessageFIFO.IsOpened == false)
            {
                responseMessageFIFO.Start();
            }
        }
        /// <summary>
        /// 响应消息队列关闭
        /// </summary>
        protected virtual void CloseResponseMessageFIFO()
        {
            if (responseMessageFIFO != null && responseMessageFIFO.IsOpened == true)
            {
                responseMessageFIFO.Stop();
            }
        }
        /// <summary>
        /// 启动前触发
        /// </summary>
        /// <param name="status"></param>
        protected virtual void RaiseOpening(bool status)
        {
            if (OnOpening != null)
            {
                OnOpening(this, true);
            }
        }
        /// <summary>
        /// 启动后触发
        /// </summary>
        /// <param name="status"></param>
        protected virtual void RaiseOpened(bool status)
        {
            if (OnOpened != null)
            {
                OnOpened(this, true);
            }
        }
        /// <summary>
        /// 关闭前触发
        /// </summary>
        /// <param name="status"></param>
        protected virtual void RaiseClosing(bool status)
        {
            if (OnClosing != null)
            {
                OnClosing(this, true);
            }
        }
        /// <summary>
        /// 关闭后触发
        /// </summary>
        /// <param name="status"></param>
        protected virtual void RaiseClosed(bool status)
        {
            if (OnClosed != null)
            {
                OnClosed(this, true);
            }
        }
        /// <summary>
        /// 连接会话建立后触发
        /// </summary>
        /// <param name="session">连接会话</param>
        /// <returns></returns>
        protected virtual ConnectSession RaiseConnectSession(ConnectSession session)
        {
            if (OnSessionAdded != null)
            {
                OnSessionAdded(session);
            }
            return session;
        }
        /// <summary>
        /// 应答数据事件
        /// </summary>
        public event ResponseHandler<IResponseData> OnResponseBuffer;
        /// <summary>
        /// 应答异常
        /// </summary>
        public event ExceptionHandler<Exception> OnException;
        /// <summary>
        /// 应答普通消息
        /// </summary>
        public event ExceptionHandler<string> OnInfo;
        /// <summary>
        /// 打开前触发
        /// </summary>
        public event ResponseHandler<bool> OnOpening;
        /// <summary>
        /// 打开后触发
        /// </summary>
        public event ResponseHandler<bool> OnOpened;
        /// <summary>
        /// 关闭前触发
        /// </summary>
        public event ResponseHandler<bool> OnClosing;
        /// <summary>
        /// 关闭后触发
        /// </summary>
        public event ResponseHandler<bool> OnClosed;
        /// <summary>
        /// 会话构建后触发
        /// </summary>
        public event SessionHandler OnSessionAdded;       
    }


实现部分的代码如下:

/// <summary>
    /// TCP主动监听模式,读取应答交互方式
    /// 此模式应答数据统一到一个线程上处理,排队进行数据应答
    /// </summary>
    internal class TCPHostSingleServerCommunication<T> : BaseCommunication
        where T : BaseMessageFilter
    {
        /// <summary>
        /// TCP连接地址
        /// </summary>
        IPEndPoint end;
        /// <summary>
        /// 网络连接的IP地址和端口号
        /// </summary>
        string endPort;
        /// <summary>
        /// 发起重连时,尝试不成功下一次连接的间隔时间
        /// </summary>
        protected Int32 periodTimeOut = 500;
        /// <summary>
        /// 已建立的会话
        /// </summary>
        private List<ConnectSession> connectSessionList = new List<ConnectSession>();
        /// <summary>
        /// 等待中的连接
        /// </summary>
        private List<IAsyncResult> waitAcceptSocketList = new List<IAsyncResult>();
        /// <summary>
        /// 连接处理锁
        /// </summary>
        private object acceptLock = new object();
        /// <summary>
        /// 用于Socket监听的托管队列
        /// </summary>
        private IoCompletionMessageFIFO acceptFIFO = new IoCompletionMessageFIFO();
        /// <summary>
        /// 监听信号量
        /// </summary>
        private ManualResetEvent acceptWaitResetEvent = new ManualResetEvent(false);
        /// <summary>
        /// 连接模式构造
        /// </summary>
        /// <param name="ip">监听的IP地址</param>
        /// <param name="port">端口号</param>
        public TCPHostSingleServerCommunication(string ip, int port)
        {
            this.end = new IPEndPoint(IPAddress.Parse(ip), port);
            this.endPort = string.Format("{0}:{1}", ip, port);
            acceptFIFO.Exceute += acceptFIFO_Exceute;
        }
        /// <summary>
        /// 监听托管队列处理回调
        /// </summary>
        /// <param name="obj"></param>
        void acceptFIFO_Exceute(object obj)
        {
            if (obj is SocketCommand)
            {
                SocketCommand socketCommand = (SocketCommand)obj;
                if (socketCommand == SocketCommand.Start)
                {
                    this.StartConnectNetWork();
                }
            }
        }
        /// <summary>
        /// 打开
        /// 如果打开失败,会自动尝试关闭掉
        /// </summary>
        public override void Open()
        {
            if (communicationParamerters == null)
            {
                throw new Exception("设备端口参数未初始化");
            }
            try
            {
                RaiseOpening(true);
                acceptFIFO.Start();
                System.Threading.Thread.Sleep(200);
                if (acceptFIFO != null && acceptFIFO.IsOpened == true)
                {
                    acceptFIFO.Post(SocketCommand.Start);
                }
                this.OpenRespnoseMessageFIFO();
            }
            catch (Exception ex)
            {
                Exception portExcp = new Exception(string.Format("网口【{0}】打开失败,失败原因:{1}", endPort, ex.Message));
                this.Post(portExcp);
                throw portExcp;
            }
        }
        /// <summary>
        /// 开始网络监听
        /// </summary>
        private void StartConnectNetWork()
        {
            try
            {
                acceptWaitResetEvent.Reset();
                Socket socket = new Socket(end.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
                socket.Bind(end);
                socket.Listen(0xFFFF);
                AsyncCallback acceptCallback = new AsyncCallback(CallbackAccept);
                lock (acceptLock)
                {
                    IAsyncResult beginAr = socket.BeginAccept(acceptCallback, socket);
                    waitAcceptSocketList.Add(beginAr);
                }
                RaiseOpened(true);
                acceptWaitResetEvent.WaitOne();
                this.StopConnectNetWork();
                System.Threading.Thread.Sleep(200);
                if (socket != null)
                {
                    socket.Close();
                }
                RaiseClosed(true);
            }
            catch (Exception ex)
            {
                this.Post(new Exception(string.Format("连接托管异常,异常原因:{0}", ex.Message)));
            }
        }
        /// <summary>
        /// 监听到一个异步连接
        /// 此处用于处理已监听到的连接,并发起新的监听连接,剔除掉死链接
        /// </summary>
        /// <param name="ar"></param>
        private void CallbackAccept(IAsyncResult ar)
        {
            if (ar.IsCompleted == false)
            {
                return;
            }
            if (IsOpen == true)
            {
                try
                {
                    byte[] inOptionValues = GetOptionValues();
                    Socket tempSocket = (Socket)ar.AsyncState;
                    Socket endAcceptSocket = tempSocket.EndAccept(ar);
                    ConnectSession connectSession = ConnectSession.Create<T>();
                    connectSession.ReciveSocket = endAcceptSocket;
                    connectSession.ReciveSocket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);//IO控制防止死连接
                    connectSession = RaiseConnectSession(connectSession);
                    connectSession.ReciveSocket.BeginReceive(connectSession.ReciveBuffer, 0, connectSession.ReciveBuffer.Length, SocketFlags.None, new AsyncCallback(OnDataRead), connectSession);
                    lock (acceptLock)
                    {
                        connectSessionList.Add(connectSession);
                        IAsyncResult tempAr = waitAcceptSocketList.Find(delegate(IAsyncResult delAr) { return delAr.AsyncWaitHandle.SafeWaitHandle.Equals(ar.AsyncWaitHandle.SafeWaitHandle); });
                        if (tempAr != null)
                        {
                            waitAcceptSocketList.Remove(tempAr);
                        }
                    }
                    IPAddress ip = ((System.Net.IPEndPoint)endAcceptSocket.RemoteEndPoint).Address;
                    int remotePort = ((System.Net.IPEndPoint)endAcceptSocket.RemoteEndPoint).Port;
                    this.Post(string.Format("远程客户端:【{0}:{1}】连接成功", ip.ToString(), remotePort));
                }
                catch (Exception ex)
                {
                    this.Post(new Exception(string.Format("新的全连接添加失败,失败原因:{0}", ex.Message)));
                }
            }
            else
            {
                try
                {
                    Socket tempSocket = (Socket)ar.AsyncState;
                    if (tempSocket == null)
                    {
                        return;
                    }
                    Socket endAcceptSocket = tempSocket.EndAccept(ar);
                    IPAddress ip = null;
                    int remotePort = 0;
                    if (endAcceptSocket != null)
                    {
                        ip = ((System.Net.IPEndPoint)endAcceptSocket.RemoteEndPoint).Address;
                        remotePort = ((System.Net.IPEndPoint)endAcceptSocket.RemoteEndPoint).Port;
                    }
                    if (endAcceptSocket != null)
                    {
                        endAcceptSocket.Close();
                    }
                    if (ip != null)
                    {
                        this.Post((string.Format("尝试关闭系统时,客户端发起的新的连接【{0}:{1}】强制关闭成功", ip.ToString(), remotePort)));
                    }
                }
                catch (Exception ex)
                {
                    this.Post(string.Format("关闭系统后发起的监听连接关闭失败,失败原因:{0}", ex.Message));
                }
            }
        }
        #region 请求写入数据
        /// <summary>
        /// 请求数据,根据会话ID发送,
        /// 一般用于并发处理场合,根据ID来确认具体的发送会话,
        /// 用于服务监听应答场合
        /// </summary>
        /// <param name="sessionID">会话ID</param>
        /// <param name="data">数据</param>
        public override void Request(Guid sessionID, byte[] data)
        {
            ConnectSession tempConnectSession;
            lock (acceptLock)
            {
                tempConnectSession = connectSessionList.Find(delegate(ConnectSession obj) { return obj.SessionID == sessionID; });
            }
            if (tempConnectSession != null)
            {
                this.SendDataEx(tempConnectSession, data);
            }
        }
        /// <summary>
        /// 请求数据,根据会话ID发送,
        /// 一般用于并发处理场合,根据ID来确认具体的发送会话,
        /// 用于服务监听应答场合
        /// </summary>
        /// <param name="sessionID">会话ID</param>
        /// <param name="data">数据</param>
        public override void Request(Guid sessionID, string data)
        {
            ConnectSession tempConnectSession;
            lock (acceptLock)
            {
                tempConnectSession = connectSessionList.Find(delegate(ConnectSession obj) { return obj.SessionID == sessionID; });
            }
            if (tempConnectSession != null)
            {
                this.SendDataEx(tempConnectSession, data);
            }
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        private void SendDataEx(ConnectSession tempConnection, object data)
        {
            byte[] tempBuffer = null;
            if (data is string)
            {
                tempBuffer = Encoding.UTF8.GetBytes((string)data);
            }
            else if (data is byte[])
            {
                tempBuffer = (byte[])data;
            }
            tempConnection.ReciveSocket.BeginSend(tempBuffer, 0, tempBuffer.Length, SocketFlags.None, new AsyncCallback(OnDataSend), tempConnection);
        }
        /// <summary>
        /// 异步发送数据
        /// </summary>
        /// <param name="ar"></param>
        protected virtual void OnDataSend(IAsyncResult ar)
        {
            ConnectSession tempSession = ar.AsyncState as ConnectSession;
            SocketError socketError;
            Int32 bufferSize = tempSession.ReciveSocket.EndSend(ar, out socketError);
            if (socketError != SocketError.Success)
            {
                this.Post(new Exception(SocketErrorInfo.GetErrorMessage(socketError)));
            }
        }
        #endregion
        #region 应答处理
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="ar"></param>
        protected virtual void OnDataRead(IAsyncResult ar)
        {
            if (IsOpen == false)//关闭连接时不再处理各种可能的数据
            {
                return;
            }
            try
            {
                ConnectSession tempSession = ar.AsyncState as ConnectSession;
                SocketError socketError;
                Int32 bufferSize = tempSession.ReciveSocket.EndReceive(ar, out socketError);
                if (socketError != SocketError.Success)
                {
                    ErrorForceClose(tempSession, socketError);
                }
                if (bufferSize == 0)
                {
                    if (IsOpen == true)
                    {
                        FoceClose(tempSession);
                    }
                    return;
                }
                tempSession.MemoryStream.Write(tempSession.ReciveBuffer, 0, bufferSize);
                if (tempSession.ReciveSocket.Available <= 0)
                {
                    byte[] buffer = tempSession.MemoryStream.ToArray();
                    tempSession.MemoryStream.Position = 0;
                    tempSession.MemoryStream.Close();
                    tempSession.MemoryStream = new MemoryStream();
                    IResponseData resopnseData = tempSession.MessageFilter.Filter(buffer);
                    if (resopnseData != null)
                    {
                        this.ParallelPost(resopnseData);
                    }
                }
                tempSession.ReciveSocket.BeginReceive(tempSession.ReciveBuffer, 0, tempSession.ReciveBuffer.Length, SocketFlags.None, new AsyncCallback(OnDataRead), tempSession);
            }
            catch (Exception ex)
            {
                if (ex is TCPConnectException)
                {
                    this.Post(string.Format("网口连接发生了一个故障,等待客户端重新建立连接,故障原因:{0}", ex.Message));
                }
                else
                {
                    this.Post(new TCPConnectException(ex.Message));
                }
            }
        }

        #endregion
        /// <summary>
        /// 关闭网路连接
        /// </summary>
        public override void Close()
        {
            try
            {
                RaiseClosing(true);
                this.CloseResponseMessageFIFO();
                acceptWaitResetEvent.Set();
                acceptFIFO.Stop();
            }
            catch (Exception ex)
            {
                Exception portException = new Exception(string.Format("网口【{0}】关闭失败,失败原因:{1}", endPort, ex.Message));
                this.Post(portException);
                throw portException;
            }
        }
        /// <summary>
        /// 错误强制关闭连接
        /// </summary>
        /// <param name="tempSession"></param>
        /// <param name="socketError"></param>
        private void ErrorForceClose(ConnectSession tempSession, SocketError socketError)
        {
            IPAddress ip = ((System.Net.IPEndPoint)tempSession.ReciveSocket.RemoteEndPoint).Address;
            int remotePort = ((System.Net.IPEndPoint)tempSession.ReciveSocket.RemoteEndPoint).Port;
            try
            {
                if (tempSession.ReciveSocket != null && tempSession.ReciveSocket.Connected == true)
                {
                    SocketAsyncEventArgs e = new SocketAsyncEventArgs();
                    e.AcceptSocket = tempSession.ReciveSocket;
                    tempSession.ReciveSocket.DisconnectAsync(e);//异常连接直接强制关闭
                }
                lock (acceptLock)
                {
                    if (connectSessionList.Contains(tempSession))
                    {
                        connectSessionList.Remove(tempSession);
                    }
                }
            }
            catch
            {

            }
            finally
            {
                string errorMessage = SocketErrorInfo.GetErrorMessage(socketError);
                if (!string.IsNullOrEmpty(errorMessage))
                {
                    throw new TCPConnectException(string.Format("端口【{0}】监听的客户端【{1}:{2}】接收数据异常,异常原因:{3}", endPort, ip.ToString(), remotePort, errorMessage));
                }
                else
                {
                    throw new TCPConnectException(string.Format("端口【{0}】监听的客户端【{1}:{2}】接收数据异常", endPort, ip.ToString(), remotePort));
                }
            }
        }
        /// <summary>
        /// 强制关闭连接
        /// </summary>
        /// <param name="tempSession"></param>
        protected virtual void FoceClose(ConnectSession tempSession)
        {
            IPAddress ip = ((System.Net.IPEndPoint)tempSession.ReciveSocket.RemoteEndPoint).Address;
            int remotePort = ((System.Net.IPEndPoint)tempSession.ReciveSocket.RemoteEndPoint).Port;
            try
            {
                if (tempSession.ReciveSocket != null && tempSession.ReciveSocket.Connected == true)
                {
                    SocketAsyncEventArgs e = new SocketAsyncEventArgs();
                    e.AcceptSocket = tempSession.ReciveSocket;
                    tempSession.ReciveSocket.DisconnectAsync(e);//异常连接直接强制关闭
                }
                lock (acceptLock)
                {
                    if (connectSessionList.Contains(tempSession))
                    {
                        connectSessionList.Remove(tempSession);
                    }
                }
            }
            catch
            {

            }
            finally
            {
                this.Post(string.Format("端口【{0}】监听的客户端【{1}:{2}】主动关闭连接,等待客户端建立新的连接", endPort, ip.ToString(), remotePort));
            }
        }
        /// <summary>
        /// 停止网络连接,逐步释放资源
        /// </summary>
        private void StopConnectNetWork()
        {
            StringBuilder connectInfo = new StringBuilder();
            StringBuilder connectExp = new StringBuilder();
            lock (acceptLock)
            {
                if (waitAcceptSocketList.Count > 0)
                {
                    for (int i = 0; i < waitAcceptSocketList.Count; i++)
                    {
                        try
                        {
                            IAsyncResult waitAr = waitAcceptSocketList[i];
                            waitAr.AsyncWaitHandle.SafeWaitHandle.Close();
                            connectInfo.AppendLine("半连接关闭成功");
                        }
                        catch (Exception ex)
                        {
                            connectExp.AppendLine(string.Format("WaitAr释放异常,异常原因:{0}", ex.Message));
                        }
                    }
                }
                if (connectSessionList.Count > 0)
                {
                    for (int i = 0; i < connectSessionList.Count; i++)
                    {
                        try
                        {
                            Socket tempSocket = connectSessionList[i].ReciveSocket;
                            IPAddress ip = null;
                            int remotePort = 0;
                            if (tempSocket != null)
                            {
                                ip = ((System.Net.IPEndPoint)tempSocket.RemoteEndPoint).Address;
                                remotePort = ((System.Net.IPEndPoint)tempSocket.RemoteEndPoint).Port;
                            }
                            if (tempSocket != null)
                            {
                                tempSocket.Close();
                            }
                            if (ip != null)
                            {
                                connectInfo.AppendLine(string.Format("全连接对应的远程客户端【{0}:{1}】关闭成功", ip.ToString(), remotePort));
                            }
                        }
                        catch (Exception ex)
                        {
                            connectExp.AppendLine(string.Format("AcceptSocket释放异常,异常原因:{0}", ex.Message));
                        }
                    }
                }
                if (connectInfo.Length > 0)
                {
                    this.Post(connectInfo.ToString());
                }
                if (connectExp.Length > 0)
                {
                    this.Post(new Exception(connectExp.ToString()));
                }
            }
        }
        /// <summary>
        /// 获取心跳包参数
        /// </summary>
        /// <returns></returns>
        private byte[] GetOptionValues()
        {
            uint dummy = 0;
            byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
            BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
            BitConverter.GetBytes((uint)communicationParamerters.HeartRateTimeOut * 100).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
            BitConverter.GetBytes((uint)communicationParamerters.HeartRateTimeOut * 100).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
            return inOptionValues;
        }
    }


最后通过通信工厂,进行具体的业务调用和实现:

/// <summary>
    /// 通信工厂构建
    /// </summary>
    public class CommunicationFactory
    {
        /// <summary>
        /// 通信工厂构建
        /// </summary>
        /// <param name="paramerters"></param>
        /// <returns></returns>
        public static ICommunication Create<T>(CommunicationParamertercs paramerters)
            where T :BaseMessageFilter
        {
            ICommunication iCommunication = null;
            if (paramerters.CommunicationType == CommunicationType.SerialPort)
            {
                iCommunication = new SerialPortCommunication<T>(paramerters.PortName, paramerters.BaudRate);
            }
            else if (paramerters.CommunicationType == CommunicationType.TCPClient)
            {
                iCommunication = new TCPClientCommunication<T>(paramerters.Ip, paramerters.PortNO);
            }
            else if (paramerters.CommunicationType == CommunicationType.TCPServer)
            {
                iCommunication = new TCPServerCommunication<T>(paramerters.Ip, paramerters.PortNO);
            }
            if (iCommunication != null)
            {
                IMessageFilter messageFilter = (IMessageFilter)Activator.CreateInstance<T>();
                iCommunication.InitCommunication(paramerters);
            }
            return iCommunication;
        }
    }

你可能感兴趣的:(基于链表会话管理的TCP服务端实现)