终于将完整的会话机制和消息过滤机制追加到了通用通信模型中,整个通信构建在通信工厂中,通过消息过滤器注入,实现消息的解析。
此处只处理了接收消息的解析,未将发送消息过滤器作为一部分直接插入,主要是考虑到写入时的灵活性,后期逐步追加。
首先是接口的定义,接口部分实现了基本的约束。
/// <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; } }