You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

562 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using UPPLibs;
using RemoteObjects;
namespace CommService
{
/*
*TCPHandler
*
*2010-10-30
*
*/
class TCPHandler
{
public NetworkStream networkStream;
private byte[] bytes;
private bool online;
public Thread tWorker;
public bool stoped;
public string tName;
private Queue qCommand;
private Queue qSyncCommand;
private AutoResetEvent newReqEvent = new AutoResetEvent(false);
private AutoResetEvent resMatchEvent = new AutoResetEvent(false);
private Thread tReqWatcher;
public struRequestInQueue sCurrentReq;
private Mutex mut = new Mutex();
public string strIPPort;
public string sLoginTime;
private byte[] rcvBuff = { };
private int timeoutCount;
private byte seqFrame;
private TcpClient tcpClient = null;
private MessageHandler messageHandler = null;
public DateTime dtLogin;
private bool bReplace;
public bool bKickOff=false;
public TCPHandler(TcpClient tcpClient)
{
this.tcpClient = tcpClient;
networkStream = tcpClient.GetStream();
bytes = new byte[1024];
online = true;
tName = "未知终端";
qCommand = new Queue();
qSyncCommand = new Queue(qCommand);
seqFrame = 0x1;
stoped = false;
tReqWatcher = null;
bReplace = false;
messageHandler = new MessageHandler(this);
//messageHandler.Init();
}
/*
*WorkerThreadProc
*
*2010-10-30
*void
*void
*线
*/
public void WorkerThreadProc()
{
int i = 0;
// Loop to receive all the data sent by the client.
strIPPort = IPAddress.Parse(((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString())
+ ":"
+ ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port.ToString();
Common.logFile.write("[未知终端] 建立连接,来自:" + strIPPort, LogFile.LOGLVL_NORMAL);
try
{
//读取字节流
i = networkStream.Read(bytes, 0, bytes.Length);
}
catch (Exception e5)
{
Close();
Common.platForm.tcpServer.RemoveTCPHandler(this);
Common.logFile.write("采集终端 [" + this.tName + "] Exception: " + e5.ToString(), LogFile.LOGLVL_ERROR);
Common.logFile.write("采集终端 [" + this.tName + "]<<<<<<WorkerThreadProc exited>>>>>>>>", LogFile.LOGLVL_NORMAL);
return;
}
while (i != 0)
{
byte[] rcvbytes = new byte[i];
for (int j = 0; j < i; j++)
{
rcvbytes[j] = bytes[j];
}
//Common.logFile.writeHexString("[" + (this.tName == "未知终端" ? this.tName + "@" + strIPPort : this.tName) + "] " + "收到数据: ", rcvbytes, LogFile.LOGLVL_DEBUG);
//put into buffer
byte[] tmp = new byte[rcvBuff.Length + i];
for (int j = 0; j < rcvBuff.Length; j++)
{
tmp[j] = rcvBuff[j];
}
for (int j = 0; j < i; j++)
{
tmp[j + rcvBuff.Length] = bytes[j];
}
rcvBuff = tmp;
//数据包识别
byte[] pack = UPPHandler.FindPackFromBuff(ref rcvBuff);
if (this.tName == "未知终端" && pack.Length == 0)
{
break;
}
while (pack.Length > 0)
{
Common.logFile.writeHexString("[" + this.tName + "] " + "收到帧: ", pack, LogFile.LOGLVL_DEBUG);
UPPLibs.struFrame sFrame = new UPPLibs.struFrame();
//数据包解析
if (UPPHandler.frameParsing(pack, ref sFrame) == true)
{
string info2Display = "";
UPPHandler.frameCommenting(ref sFrame, ref info2Display);
Common.logFile.write("[" + this.tName + "] " + "收到 " + info2Display, LogFile.LOGLVL_DEBUG);
messageHandler.messageHandling(ref sFrame);
}
//数据包识别
pack = UPPHandler.FindPackFromBuff(ref rcvBuff);
}
try
{
i = networkStream.Read(bytes, 0, bytes.Length);
}
catch (Exception e5)
{
Common.logFile.write("采集终端 [" + this.tName + "] Exception: " + e5.ToString(), LogFile.LOGLVL_ERROR);
break;
}
}
// Shutdown and end connection
if (online == true && (this.tName.CompareTo("未知终端")!=0))
{
SaveOfflineInfo(DateTime.Now);
}
else if (online == false && (this.tName.CompareTo("未知终端") != 0))
{
if (bReplace == true)
{
SaveReplaceInfo(DateTime.Now);
}
else if (bKickOff == true)
{
SaveKickoffInfo(DateTime.Now);
}
else
{
SaveCloseInfo(DateTime.Now);
}
}
Close();
//Common.TCPWorkerList.Remove(this);
Common.platForm.tcpServer.RemoveTCPHandler(this);
Common.logFile.write("采集终端 [" + this.tName + "]<<<<<<WorkerThreadProc exited>>>>>>>>", LogFile.LOGLVL_NORMAL);
}
/*
*messageMatching
*
*2010-10-30
*ref struFrame sFrame
*bool true false
*
*/
public bool messageMatching(ref struFrame sFrame)
{
bool matchOK = false;
//lock
mut.WaitOne();
//check current request with sFrame
if (sFrame.flagFSEQ == sCurrentReq.frameInfo.flagFSEQ
&& sFrame.flagCtrlF == sCurrentReq.frameInfo.flagCtrlF)
{
struFrame currentFrame = new struFrame();
UPPHandler.frameCopy(ref sCurrentReq.frameInfo, ref currentFrame);
sFrame.userData2 = (object)currentFrame;
//sCurrentReq.frameResp = new struFrame();
//取回数据
UPPHandler.frameCopy(ref sFrame, ref sCurrentReq.frameResp);
sCurrentReq.bMatchOK = true;
matchOK = sCurrentReq.bMatchOK;
try
{
resMatchEvent.Set();
sCurrentReq.handleReqEvent.Set();
//Common.logFile.write("sCurrentReq matching" + sCurrentReq.GetHashCode().ToString(), LogFile.LOGLVL_NORMAL);
//Common.logFile.write("sCurrentReq.frameResp" + sCurrentReq.frameResp.GetHashCode().ToString(), LogFile.LOGLVL_NORMAL);
}
catch (Exception e1)
{
Common.logFile.write("FSEQ:" + sFrame.flagFSEQ + "\r\nAutoResetEvent, Exception: " + e1.ToString(), LogFile.LOGLVL_ERROR);
}
}
else
{
Common.logFile.write("消息匹配 错误!!!!!", LogFile.LOGLVL_NORMAL);
}
//unlock
mut.ReleaseMutex();
return matchOK;
}
/*
*Start
*
*2010-10-30
*void
*void
*线
*/
public void Start()
{
tWorker = new Thread(new ThreadStart(WorkerThreadProc));
tWorker.IsBackground = true;
tWorker.Start();
}
/*
*GetSeqFrame
*
*2010-10-30
*void
*byte
*
*/
public byte GetSeqFrame()
{
byte res = seqFrame;
seqFrame++;
if (seqFrame >= 0x80)
{
seqFrame = 0x1;
}
return res;
}
/*
*PutNewReq
*
*2010-10-30
*ref struRequestInQueue reqInQ
*void
*
*/
public void PutNewReq(ref struRequestInQueue reqInQ) //
{
if (tReqWatcher == null || tReqWatcher.IsAlive == false)
{
tReqWatcher = new Thread(new ThreadStart(WatcherThreadProc));
tReqWatcher.Start();
}
Object obj = reqInQ;
qSyncCommand.Enqueue(obj);
//Console.WriteLine("put command:{0} into queue", n);
newReqEvent.Set();
}
/*
*SetTimeOut
*
*2010-10-30
*int interval
*void
*
*/
public void SetTimeOut(int interval)
{
timeoutCount = interval;
}
/*
*CheckTimeOut
*
*2010-10-30
*void
*bool true false
*
*/
public bool CheckTimeOut()
{
bool res = true;
timeoutCount--;
if (timeoutCount < 0)
{
res = false;
}
return res;
}
/*
*remakeTimeCorrectingFrame
*
*2010-10-30
*ref byte[] frameBytes
*void
*
*/
private void remakeTimeCorrectingFrame(ref byte[] frameBytes)
{
if (frameBytes.Length == 20)
{
DateTime dtNow = DateTime.Now;
frameBytes[12] = (byte)Convert.ToInt32(dtNow.Second.ToString("D2"), 16);//秒
frameBytes[13] = (byte)Convert.ToInt32(dtNow.Minute.ToString("D2"), 16);//分
frameBytes[14] = (byte)Convert.ToInt32(dtNow.Hour.ToString("D2"), 16);//时
frameBytes[15] = (byte)Convert.ToInt32(dtNow.Day.ToString("D2"), 16);//日
frameBytes[16] = (byte)Convert.ToInt32(dtNow.Month.ToString("D2"), 16);//月
frameBytes[17] = (byte)Convert.ToInt32((dtNow.Year % 100).ToString("D2"), 16);//年
//重新计算 CS
frameBytes[18] = (byte)UPPLibs.UPPHandler.countCS(frameBytes, 0, frameBytes.Length - 2);
}
}
/*
*WatcherThreadProc
*
*2010-10-30
*void
*void
*线
*/
public void WatcherThreadProc()
{
bool loop = true;
while (loop)
{
//新消息通知
if (newReqEvent.WaitOne(8000, false) == true)
{
while (qSyncCommand.Count > 0)
{
//设置当前请求
byte[] frameBytes = null;
bool isTimeCorrectting = false;
mut.WaitOne();
sCurrentReq = (struRequestInQueue)qSyncCommand.Dequeue();
//Common.logFile.write("sCurrentReq" + sCurrentReq.GetHashCode().ToString(), LogFile.LOGLVL_NORMAL);
frameBytes = sCurrentReq.frameBytes;
isTimeCorrectting = sCurrentReq.frameInfo.isTimeCorrectting;
mut.ReleaseMutex();
//Console.WriteLine("current command:{0} waiting for answer", n);
resMatchEvent.Reset();
int cycleCount = 0;
bool matchOK = false;
//最多重发三次
while (cycleCount < 3)
{
if (isTimeCorrectting == true)
{
remakeTimeCorrectingFrame(ref frameBytes);
}
try
{
networkStream.Write(frameBytes, 0, frameBytes.Length);
Common.logFile.writeHexString("发送请求帧[" + this.tName + "]", frameBytes, LogFile.LOGLVL_NORMAL);// write("获取终端[" + tw.tName + "]主动上传间隔(分钟):" + sInterval, LogFile.LOGLVL_NORMAL);
}
catch (Exception e)
{
//Common.logFile.write("数据发送出现例外:"+e.ToString(), LogFile.LOGLVL_ERROR);
break;
}
//等待应答消息
if (resMatchEvent.WaitOne(3000, false) == true)
{
break;
}
else
{
//Console.WriteLine("get a commmand event timeout");
cycleCount++;
}
// 通知 service ,返回结果
mut.WaitOne();
matchOK = sCurrentReq.bMatchOK;
mut.ReleaseMutex();
if (matchOK == true)
{
break;
}
}
}
}
else
{
qSyncCommand.Clear();
loop = false;
}
}
}
/*
*Close
*
*2010-10-30
*void
*void
*
*/
public void Close()
{
//lock
//TCPServer.mut.WaitOne();
try
{
if (online == true)
{
//if(Thread.CurrentThread == this.tWorker && this.tName != "未知终端")
//{
// SaveOfflineInfo(DateTime.Now);
//}
online = false;
networkStream.Close();
tcpClient.Close();
if (tReqWatcher != null && tReqWatcher.IsAlive == true)
{
tReqWatcher.Abort();
}
qSyncCommand.Clear();
}
}
catch (Exception e1)
{
}
}
public void ExecuteTiming()
{
Thread t = new Thread(new ThreadStart(TimingThreadProc));
t.IsBackground = true;
t.Start();
}
/*
*SaveLoginInfo
*
*2010-10-30
*DateTime dtLoginTime
*void
*
*/
public void TimingThreadProc()
{
ReqHandler reqHandler = new ReqHandler();
reqHandler.SetTime(this.tName);
}
/*
*SaveKickoffInfo
*
*2010-10-30
*DateTime dtLogoutTime
*void
*
*/
public void SaveKickoffInfo(DateTime dtLogoutTime)
{
messageHandler.SaveLogoutInfo(this.tName, this.dtLogin, dtLogoutTime, 1);
Common.logFile.write("[" + this.tName + "] 踢出 Kickoff", LogFile.LOGLVL_NORMAL);
}
/*
*SaveOfflineInfo
*
*2010-10-30
*DateTime dtLogoutTime 线
*void
*线
*/
public void SaveOfflineInfo(DateTime dtLogoutTime)
{
messageHandler.SaveLogoutInfo(this.tName, this.dtLogin, dtLogoutTime, 0);
Common.logFile.write("[" + this.tName + "] 掉线 Offline", LogFile.LOGLVL_NORMAL);
}
/*
*SaveCloseInfo
*
*2010-10-30
*DateTime dtLogoutTime 线
*void
*线
*/
public void SaveCloseInfo(DateTime dtLogoutTime)
{
messageHandler.SaveLogoutInfo(this.tName, this.dtLogin, dtLogoutTime, 2);
Common.logFile.write("[" + this.tName + "] 被服务关闭 Offline", LogFile.LOGLVL_NORMAL);
}
/*
*SaveCloseInfo
*
*2010-10-30
*DateTime dtLogoutTime 线
*void
*线
*/
public void SaveReplaceInfo(DateTime dtLogoutTime)
{
messageHandler.SaveLogoutInfo(this.tName, this.dtLogin, dtLogoutTime, 3);
Common.logFile.write("[" + this.tName + "] 被同名替代 Offline", LogFile.LOGLVL_NORMAL);
}
public void SetReplaceFlag(bool bOn)
{
bReplace = bOn;
}
}
}