using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading.Tasks; using static JiangsuEarthquake.Common.Sockets; namespace JiangsuEarthquake.Common { public class Server : SocketObject { public PushSockets pushSockets; bool IsStop = false; object obj = new object(); /// /// 信号量 /// private Semaphore semap = new Semaphore(5, 5000); /// /// 客户端队列集合 /// public List ClientList = new List(); /// /// 服务端 /// private TcpListener listener; /// /// 当前IP地址 /// private IPAddress Ipaddress; /// /// 校时信息 /// public List TimingList = new List(); /// /// 当前监听端口 /// private int Port; /// /// 当前IP,端口对象 /// private IPEndPoint ip; /// /// 初始化服务端对象 /// /// IP地址 /// 监听端口 public override void InitSocket(IPAddress ipaddress, int port) { Ipaddress = ipaddress; Port = port; listener = new TcpListener(Ipaddress, Port); } /// /// 初始化服务端对象 /// /// IP地址 /// 监听端口 public override void InitSocket(string ipaddress, int port) { Ipaddress = IPAddress.Parse(ipaddress); Port = port; ip = new IPEndPoint(Ipaddress, Port); listener = new TcpListener(Ipaddress, Port); } /// /// 启动监听,并处理连接 /// public override bool Start() { try { listener.Start(); Thread AccTh = new Thread(new ThreadStart(delegate { while (true) { if (IsStop != false) { break; } GetAcceptTcpClient(); Thread.Sleep(1); } })); AccTh.Start(); return true; } catch (SocketException skex) { Sockets sks = new Sockets(); sks.ex = skex; if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI return false; } } /// /// 停止 /// public override void Stop() { if (listener != null) { listener.Stop(); listener = null; IsStop = true; pushSockets = null; } } /// /// 等待处理新的连接 /// private void GetAcceptTcpClient() { try { if (listener.Pending()) { semap.WaitOne(); TcpClient tclient = listener.AcceptTcpClient(); //维护客户端队列 Socket socket = tclient.Client; NetworkStream stream = new NetworkStream(socket, true); //承载这个Socket Sockets sks = new Sockets(tclient.Client.RemoteEndPoint as IPEndPoint, tclient, stream); sks.NewClientFlag = true; //推送新客户端 if (pushSockets != null) pushSockets.Invoke(sks); //客户端异步接收 sks.nStream.BeginRead(sks.RecBuffer, 0, sks.RecBuffer.Length, new AsyncCallback(EndReader), sks); //加入客户端集合. AddClientList(sks); //主动向客户端发送校时信息 if (stream.CanWrite) { TimingList.Clear(); TimingList.AddRange(new byte[2] { 0xFE, 0xEF }); //帧头(H=0xFE 0xEF) TimingList.AddRange(new byte[2] { 0x00, 0x08 }); //长度(L=4+4)(MSH MSL)(从地址码到最后) TimingList.Add(0x00); //地址码(ADDR=00) TimingList.Add(0x06); //功能码(FUNC=06) TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 8, 0, 0, 0); int totalSeconds = (int)ts.TotalSeconds; string hexSeconds = totalSeconds.ToString("X2"); byte[] timeByte = Tools.HexStringToByteArray(hexSeconds); TimingList.AddRange(timeByte); //UTC时间 byte checkSum = Tools.CheckSum(TimingList.ToArray()); TimingList.Add(checkSum); //校验(CS = 帧头 ...+... 传感器数据) TimingList.Add(0x16); //结束符(0x16) stream.Write(TimingList.ToArray(), 0, TimingList.Count); } semap.Release(); } } catch { return; } } /// /// 异步接收发送的信息. /// /// private void EndReader(IAsyncResult ir) { Sockets sks = ir.AsyncState as Sockets; if (sks != null && listener != null) { try { if (sks.NewClientFlag || sks.Offset != 0) { sks.NewClientFlag = false; sks.Offset = sks.nStream.EndRead(ir); if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI sks.nStream.BeginRead(sks.RecBuffer, 0, sks.RecBuffer.Length, new AsyncCallback(EndReader), sks); } } catch (Exception skex) { lock (obj) { //移除异常类 ClientList.Remove(sks); Sockets sk = sks; sk.ClientDispose = true;//客户端退出 sk.ex = skex; if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } } } } /// /// 加入队列. /// /// private void AddClientList(Sockets sk) { //虽然有信号量,还是用lock增加系数 lock (obj) { Sockets sockets = ClientList.Find(o => { return o.Ip == sk.Ip; }); //如果不存在则添加,否则更新 if (sockets == null) { ClientList.Add(sk); } else { ClientList.Remove(sockets); ClientList.Add(sk); } } } /// /// 向所有在线的客户端发送信息. /// /// 发送的byte[] public void SendToAll(byte[] SendData) { try { Parallel.ForEach(ClientList, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, item => { if (item != null) SendToClient(item.Ip, SendData); }); } catch (Exception ex) { //Console.Write(ex.Message); } } /// /// 向某一位客户端发送信息 /// /// 客户端IP+端口地址 /// 发送的数据包 public void SendToClient(IPEndPoint ip, byte[] SendData) { try { Sockets sks = ClientList.Find(o => { return o.Ip == ip; }); if (sks == null || !sks.Client.Connected || sks.ClientDispose) { //没有连接时,标识退出 Sockets ks = new Sockets(); sks.ClientDispose = true;//标识客户端下线 sks.ex = new Exception("客户端无连接"); if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI ClientList.Remove(sks); } if (sks.Client.Connected) { //获取当前流进行写入. NetworkStream nStream = sks.nStream; if (nStream.CanWrite) { //byte[] buffer = Encoding.UTF8.GetBytes(SendData); nStream.Write(SendData, 0, SendData.Length); } else { //避免流被关闭,重新从对象中获取流 nStream = sks.Client.GetStream(); if (nStream.CanWrite) { //byte[] buffer = Encoding.UTF8.GetBytes(SendData); nStream.Write(SendData, 0, SendData.Length); } else { //如果还是无法写入,那么认为客户端中断连接. ClientList.Remove(sks); Sockets ks = new Sockets(); sks.ClientDispose = true;//如果出现异常,标识客户端下线 sks.ex = new Exception("客户端无连接"); if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } } } } catch (Exception skex) { Sockets sks = new Sockets(); sks.ClientDispose = true;//如果出现异常,标识客户端退出 sks.ex = skex; if (pushSockets != null) pushSockets.Invoke(sks);//推送至UI } } } }