using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; namespace Bro.Common.Link { // 客户端动作代理 public delegate void OnClientOpen(TcpClient client); public delegate void OnClientClose(TcpClient client); public delegate void OnClientRecv(TcpClient client); /// /// TCP服务器 /// public class TCPSvr { private static object synObj = new object(); public OnClientOpen ClientOpen; public OnClientClose ClientClose; public OnClientRecv ClientRecv; // 服务器描述 public string Desp {get;set;} // 服务器IP public string ServerIP { get;set; } // 服务器端口 public int ServerPort { get; set; } // 服务器监听 private TcpListener tcpSvr = null; // 停止标示 private bool bStop = false; // 监听线程 private Thread listenThread; private Thread pollThread; private Dictionary clientsMap = new Dictionary(); public TCPSvr() { } public TCPSvr(string ip, int port) { ServerIP = ip; ServerPort = port; } /// /// 初始化 /// /// public bool Init() { try { var ip = IPAddress.Parse(ServerIP); tcpSvr = new TcpListener(ip, ServerPort); bStop = false; } catch(Exception ex) { Trace.TraceError("TCP server init fail,ex:{0}", ex); return false; } return true; } /// /// 启动监听 /// /// public bool Start() { try { clientsMap.Clear(); tcpSvr.Start(); listenThread = new Thread(new ThreadStart(DoAcceptCallBack)); listenThread.Start(); pollThread = new Thread(new ThreadStart(PollThread)); pollThread.Start(); bStop = false; } catch(Exception ex) { Trace.TraceError("TCP server start listen fail,ex:{0}", ex); return false; } return true; } /// /// 停止监听 /// public void Stop() { bStop = true; try { tcpSvr.Stop(); listenThread.Join(); pollThread.Join(); } catch(Exception ex) { Trace.TraceError("TCP server stop listen fail,ex:{0}", ex); } bStop = true; } /// /// 关闭客户端 /// /// public void Close(TcpClient client) { lock(synObj) { clientsMap.Remove(client.Client); client.Close(); } } /// /// 移除客户端监听 /// /// public void Remove(TcpClient client) { lock (synObj) { clientsMap.Remove(client.Client); } } /// /// 监听线程 /// private void PollThread() { for(;;) { if (bStop) { CloseAllClient(); Trace.TraceInformation("{0} tcp server stop trigger", Desp); break; } lock(synObj) { PollRecv(); } } Trace.TraceInformation("{0} tcp server stop finish", Desp); } /// /// 新接入客户端连接 /// /// private void DoAcceptCallBack() { for (; ; ) { TcpClient client = null; try { if (!tcpSvr.Pending()) { Thread.Sleep(100); continue; } client = tcpSvr.AcceptTcpClient(); // 接收发送缓存大小 client.ReceiveBufferSize = 2048; client.SendBufferSize = 2048; // 读写超时 client.SendTimeout = 2000; client.ReceiveTimeout = 200; lock (synObj) { clientsMap.Add(client.Client, client); // 通知客户端连接进入 if (null != ClientOpen) { Trace.TraceInformation("DoAcceptCallBack {0} tcp server, accept client{1}", Desp, client.Client.RemoteEndPoint); ClientOpen(client); } } } catch (Exception ex) { client?.Close(); Trace.TraceInformation("DoAcceptCallBack fail, ex:{0},{1} tcp server, accept client{2}", ex.Message, Desp, client?.Client.RemoteEndPoint.ToString()); return; } } } /// /// 检查数据接收 /// private void PollRecv() { var rList = new ArrayList(); var eList = new ArrayList(); foreach(var item in clientsMap) { var socket = item.Key; rList.Add(socket); eList.Add(socket); } if (clientsMap.Count == 0) { Thread.Sleep(200); return; } try { Thread.Sleep(200); Socket.Select(rList, null, eList, 200); // 客户端异常则关闭 foreach(var item in eList) { Socket socket = (Socket)item; TcpClient client; if ( clientsMap.TryGetValue(socket, out client) && null != ClientClose ) { client.Close(); ClientClose(client); } clientsMap.Remove(socket); } // 客户端是否有数据 foreach(var item in rList) { Socket socket = (Socket)item; TcpClient client; if ( clientsMap.TryGetValue(socket, out client) && null != ClientRecv ) { ClientRecv(client); } } } catch(Exception ex) { Trace.TraceInformation("CloseAllClient except{0}, {1} tcp server", ex.Message, Desp); } } /// /// 关闭所有客户端连接 /// private void CloseAllClient() { Trace.TraceInformation("CloseAllClient {0} tcp server, client cnt{0}", Desp, clientsMap.Count); foreach(var item in clientsMap) { var client = item.Value; try { client.Close(); if ( null != ClientClose ) { ClientClose(client); } } catch(Exception ex) { Trace.TraceInformation("CloseAllClient except{0}, {1} tcp server, accept client{2}", ex.Message, Desp, client.Client.RemoteEndPoint); } } clientsMap.Clear(); } } }