using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Diagnostics; namespace FObjBase { /// /// 解码 /// /// /// /// public delegate bool ParsePacketHandler(byte[] packet, IFConn conn); /// /// /// public class TCPConn:IFConn { static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 需要CRC校验 /// public bool HasCRC = false; TimeSpan Heartbeat_Interval = TimeSpan.FromSeconds(3); // heartbeat包发送间隔时间,3秒 TimeSpan Silent_Time = TimeSpan.FromSeconds(10); // 单位ms没有收到任何东西的时间,10秒 const int MAX_BUFFER = 20 * 0x4000;//20个大包, 大包的尺寸在FObjSys 定义 List in_buffer = new List(MAX_BUFFER); List out_buffer = new List(MAX_BUFFER); /// /// 通信超时判断 /// Stopwatch stopwatch_comm = new Stopwatch(); /// /// 心跳包判断 /// Stopwatch stopwatch_heatbeat = new Stopwatch(); /// /// /// public ParsePacketHandler ParsePacket = null; /// /// /// public Socket sock; /// /// /// protected bool first_poll=true; /// /// /// public TCPConn() { } /// /// /// /// public TCPConn(Socket sock) { this.sock = sock; } /// /// 发送数据 /// /// /// public virtual int SendPacket(byte[] buffer) { lock (out_buffer) { int len = buffer.Length; out_buffer.AddRange(buffer); return len; } } /// /// 从包提取数据 /// /// protected virtual int GetRecvInfoPacket() // return length of the packet { int len = in_buffer.Count(); if (len < 2) return 0; byte[] bs = new byte[2]; int plen = BitConverter.ToUInt16(in_buffer.GetRange(0, 2).ToArray(), 0); if (plen > 0x4000 * 2) { //包太大,不正常!!!!!! //断开重新连接 logger.Error("TCPConn GetRecvInfoPacket 包太大,不正常, 断开重新连接"); sock.Close(); return -1; } else if (plen < 2) { //异常,包最短也有2个byte logger.Error($"TCPConn GetRecvInfoPacket 包.Size = {plen},太小,不正常, 断开重新连接"); sock.Close(); return -1; } if (len < plen) { return 0; } if (HasCRC) //TODO { if (plen < 4) { // logger.Error("TCPConn GetRecvInfoPacket 包.Size < 4, 无法 CRC 校验。 断开重新连接"); sock.Close(); return -1; } UInt16 crc = Misc.CRC.CRC16(in_buffer, 0, plen - 2); int packet_crc_idx = plen - 2; UInt16 packet_crc = BitConverter.ToUInt16(in_buffer.GetRange(packet_crc_idx, 2).ToArray(), 0); if (crc != packet_crc) { logger.Error("TCPConn GetRecvInfoPacket CRC != packet_crc 断开重新连接"); //断开重新连接 sock.Close(); return -1; } } if (len >= plen) { return plen; } return 0; } /// /// 解包 /// /// /// protected virtual bool Parse_Packet(int len) { byte[] packet = in_buffer.GetRange(0, len).ToArray(); in_buffer.RemoveRange(0, len); return ParsePacket(packet, this); } /// /// 发送心跳包 /// void Send_HeartBeat() { byte[] buf = new byte[2]; buf[0] = 0x02; buf[1] = 0x00; SendPacket(buf); return; } int Send_Poll2() { if (out_buffer.Count() == 0) { if (stopwatch_heatbeat.Elapsed > Heartbeat_Interval) { Send_HeartBeat();//是时候把心跳包放入发送缓存!!! } else return 0; } stopwatch_heatbeat.Restart(); return Send_Poll(); } int Send_Poll() { if (out_buffer.Count() == 0)//没数据,直接返回 return 0; lock (out_buffer) { int cnt_total = 0; while (out_buffer.Count() > 0)//只有有数据发送,且能发送,没有 block, 就会一直循环 { int cnt; try { cnt = sock.Send(out_buffer.ToArray()); } catch (System.Net.Sockets.SocketException e) { if (e.SocketErrorCode == SocketError.WouldBlock)//当前发不了,退出循环,等下次!!!! break; logger.Error(e, "TCPConn Send_Poll 发送异常"); return -1;//异常,断开连接!!! } if (cnt > 0) { out_buffer.RemoveRange(0, cnt);//发送成功,删除!!! cnt_total+=cnt; } else { break; } } return cnt_total;//返回总发送量 } } int Receive_Poll() { int reclen_total = 0; while (true) { int reclen; try { reclen = sock.Available; } catch (System.Net.Sockets.SocketException e) { //FDEBUG.Debug.LogMessage(this, 10, "Receive_Poll e=" + e.ToString()); if (reclen_total == 0) { logger.Error(e,"TCPConn Receive_Poll 什么都收不到"); return -1; } else return reclen_total; } if (reclen == 0) return reclen_total; byte[] buf = new byte[reclen]; try { reclen = sock.Receive(buf); } catch (System.Net.Sockets.SocketException e) { //FDEBUG.Debug.LogMessage(this, 10, "Receive_Poll e=" + e.ToString()); if (reclen_total == 0) { logger.Error(e, "TCPConn Receive_Poll 什么都收不到"); return -1; } else return reclen_total; } if (reclen > 0) { in_buffer.AddRange(buf); reclen_total += reclen; stopwatch_comm.Restart(); } } } protected void Init() { if (first_poll) { stopwatch_comm.Restart(); stopwatch_heatbeat.Restart(); first_poll = false; } } public virtual int OnPoll() { int ret=0; Init(); int reclen = Receive_Poll(); if (reclen < 0) { ret = -1; goto end; } else if (reclen == 0) { if (stopwatch_comm.Elapsed > Silent_Time) { logger.Error("TCPConn OnPoll 长时间没收到任何数据 断开连接"); ret = -2; goto end; } } else { while (true) { int packet_len = GetRecvInfoPacket(); if (packet_len > 0) { Parse_Packet(packet_len); } else if (packet_len == 0) { break; } else { //异常 ret = -1; goto end; } } } int sendlen = Send_Poll2(); if (sendlen < 0) { ret = -1; goto end; } end: if (ret != 0) { //连接断开,清空接收缓存区 logger.Error("TCPConn OnPoll 连接断开,清空接收缓存区"); in_buffer.Clear(); lock(out_buffer) { out_buffer.Clear(); } Enable = false; } return ret; } #region IFConn 成员 public ConnectHandler ConnectAction { get; set; } protected bool isconnected = false; public virtual bool IsConnected { get { return isconnected; } set { if (isconnected != value) { isconnected = value; ConnectAction(this); } } } protected bool enable=false; public bool Enable { get { return enable; } set { enable = value; if (enable == false) { Stop(); } } } protected virtual void Stop() { if (sock != null) sock.Close(); IsConnected = false; } #endregion #region IFConn 成员 public uint TranID { get; set; } #endregion } }