using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace FObjBase { public delegate bool ParsePacketHandler(byte[] packet, IFConn conn); public class TCPConn:IFConn { 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 定义 protected List in_buffer = new List(MAX_BUFFER); protected int packet_start; protected int packet_len; protected List out_buffer = new List(MAX_BUFFER); protected DateTime comm_time; protected DateTime heartbeat_time = DateTime.Now; 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) { int len = buffer.Length; out_buffer.AddRange(buffer); return len; } protected virtual int GetRecvInfoPacket() // return length of the packet { int len = in_buffer.Count() - packet_start; if (len < 2) return 0; byte[] bs = new byte[2]; int plen = BitConverter.ToUInt16(in_buffer.GetRange(packet_start, 2).ToArray(), 0); if (plen > 20000) { //包太大,不正常!!!!!! //断开重新连接 sock.Close(); return -1; } if (len < plen) { return 0; } if (HasCRC) //TODO { UInt16 crc = Misc.CRC.CRC16(in_buffer, packet_start, plen - 2); int packet_crc_idx = packet_start + plen - 2; UInt16 packet_crc = BitConverter.ToUInt16(in_buffer.GetRange(packet_crc_idx, 2).ToArray(), 0); if (crc != packet_crc) { Misc.Log.LogMessage("TCPConn.cs", 1, "CRC != packet_crc"); //断开重新连接 sock.Close(); return -1; } } if (len >= plen) { return plen; } return 0; } protected virtual bool Parse_Packet() { byte[] packet = in_buffer.GetRange(packet_start, packet_len).ToArray(); return ParsePacket(packet, this); } protected virtual int Clear_Packet() { if (packet_start > 0) { in_buffer.RemoveRange(0, packet_start); } return in_buffer.Count(); } 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 ((DateTime.Now - heartbeat_time) > Heartbeat_Interval) { Send_HeartBeat(); } else return 0; } heartbeat_time = DateTime.Now; return Send_Poll(); } int Send_Poll() { int cnt_total = 0; if (out_buffer.Count() == 0) return 0; while (out_buffer.Count() > 0) { int cnt; try { cnt = sock.Send(out_buffer.ToArray()); } catch (System.Net.Sockets.SocketException e) { if (e.ErrorCode == 10035) break; 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) 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) return -1; else return reclen_total; } if (reclen > 0) { in_buffer.AddRange(buf); reclen_total += reclen; comm_time = DateTime.Now; } } } protected void Init() { if (first_poll) { comm_time = DateTime.Now; heartbeat_time = DateTime.Now; 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 ((DateTime.Now-comm_time) > Silent_Time) { //FDEBUG.Debug.LogMessage(this, 10, "ERROR 超时出错!"); ret = -2; goto end; } } else { packet_start = 0; while (true) { packet_len = GetRecvInfoPacket(); if (packet_len > 0) { Parse_Packet(); packet_start += packet_len; } else if (packet_len == 0) { Clear_Packet(); break; } else { Clear_Packet(); ret = -1; goto end; } } } int sendlen = Send_Poll2(); if (sendlen < 0) { ret = -1; goto end; } end: if (ret != 0) { //连接断开 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 } }