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
}
}