监听器宿主是windows服务,
windows服务代码:
public partial class KFService : ServiceBase
{
Server Srv = new Server();
public KFService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
string Msg;
if (!Srv.Start(out Msg))
{
throw new Exception(Msg);
//this.Stop();
//this.EventLog.WriteEntry(Msg);
}
}
protected override void OnStop()
{
Srv.Stop();
}
}
Server.cs
public class Server
{
/// <summary>
/// 主服务线程
/// </summary>
private Thread _VSTServiceProccess;
/// <summary>
/// TCP服务Socket
/// </summary>
private TcpListener _PDAService;
/// <summary>
/// 服务超时间隔
/// </summary>
private int _ServiceTimeOut;
/// <summary>
/// 服务器的IP
/// </summary>
private IPAddress _ServerIP;
/// <summary>
/// 服务器的服务端口
/// </summary>
private int _ServerPoint;
private byte[] _TransmitKey = null;
private string _TransmitReaderSn = null;
//Distinguisher.DistinguisherEquement _DrEquement = null;
private void WriteLog(string Msg)
{
try
{
WritLogFile.Log.WriteFile(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff-->") + Msg);
}
catch
{ }
}
public Server()
{
_ServiceTimeOut = 60;
_ServerIP = IPAddress.Any;
_ServerPoint = 33555;
if (!int.TryParse(ConfigurationManager.AppSettings["ServerPort"], out _ServerPoint))
{
_ServerPoint = 33555;
WriteLog("ServerStart:获取主通信端口失败");
}
}
/// <summary>
/// 服务进程启动
/// </summary>
public bool Start(out string ErrMsg)
{
ErrMsg = null;
try
{
if (_VSTServiceProccess != null)
{
_VSTServiceProccess.Abort();
_VSTServiceProccess = null;
}
Thread.Sleep(50);
//本地打开TCP监听
_PDAService = new TcpListener(_ServerIP, _ServerPoint);
_PDAService.Start();
/*循环接收_PDAService监听数据
* 创建后台线程m_SendDatas用来发送数据
* 最后创建一个新线程ServiceProccess,用来处理已收到的TCP请求,调用m_SendDatas异步发送数据
*/
_VSTServiceProccess = new Thread(this.PDAServiceProccess);
_VSTServiceProccess.Start();
WriteLog("服务启动成功,端口号:" + _ServerPoint.ToString());
return true;
}
catch (Exception ex)
{
ErrMsg = "服务器启动失败,异常信息 :" + ex.Message;
WriteLog(ErrMsg);
return false;
}
}
/// <summary>
/// 停止服务
/// </summary>
public void Stop()
{
if (_VSTServiceProccess != null)
{
try
{
_PDAService.Server.Shutdown(SocketShutdown.Both);
}
catch { }
try
{
_PDAService.Stop();
}
catch { }
try
{
_VSTServiceProccess.Abort();
_VSTServiceProccess = null;
}
catch { }
}
}
/// <summary>
/// 主服务处理程序
/// </summary>
private void PDAServiceProccess()
{
while (true)
{
try
{
TcpClient Client = _PDAService.AcceptTcpClient();
Transmission CS = new Transmission(Client, _ServiceTimeOut, _TransmitKey);
Thread ServiceProccess = new Thread(CS.ClientServiceStart);
ServiceProccess.Start();
}
catch
{
break;
};
}
WriteLog("服务器停止运行!");
}
}
Transmission.cs
public class Transmission
{
private TcpClient _Client;
private System.Threading.Timer _TimerCheckConn = null;
private System.Threading.TimerCallback _TimerCallback = null;
private DateTime _LastDatetime = DateTime.Now;
private int _Anys = 10000;
private int _TimeOut = 30;
private BackgroundWorker m_SendDatas;
private static object _Sync = new object();
private byte[] _TransmitKey = new byte[8] { 0xc9, 0xda };
private byte[] ServerTPDU = { 0x00, 0x00 };
private byte[] ClientTPDU = { 0x00, 0x00 };
public static void WriteLog(string Msg)
{
try
{
WritLogFile.Log.WriteFile(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff-->") + Msg);
//_LogSW.Flush();
}
catch
{ }
}
public Transmission(TcpClient Client, int ServiceOut, byte[] TranKey)
{
_Client = Client;
_TimeOut = ServiceOut;
_Client.NoDelay = true;
_Client.Client.SendBufferSize = 2048; 接收窗口大小是1360
_Client.Client.ReceiveBufferSize = 10240;
if (_Client == null)
{
WriteLog("不可用的TCP连接Client is null");
throw new Exception("不可用的TCP连接");
}
if (!_Client.Connected)
{
WriteLog("不可用的TCP连接Client not Connected");
throw new Exception("不可用的TCP连接");
}
if (TranKey != null)
_TransmitKey = TranKey;
m_SendDatas = new BackgroundWorker();// 申明后台对象
m_SendDatas.WorkerSupportsCancellation = true; // 设置可以取消
m_SendDatas.DoWork += new DoWorkEventHandler(SendDatas);
_TimerCallback = new System.Threading.TimerCallback(this.TimerCheckConn_Tick);
_TimerCheckConn = new System.Threading.Timer(_TimerCallback, null, _Anys / 2, _Anys);
}
private void TimerCheckConn_Tick(object obj)
{
if (_LastDatetime.AddMinutes(_TimeOut) < DateTime.Now)
{
try
{
if (m_SendDatas.IsBusy)
m_SendDatas.CancelAsync();
WriteLog(_Client.Client.RemoteEndPoint.ToString() + "连接最后响应时间:" + _LastDatetime.ToString("yyyy/MM/dd HH:mm:ss"));
_TimerCheckConn.Dispose();
_Client.Client.Shutdown(SocketShutdown.Both);
_Client.Client.Close();
GC.Collect();
}
catch
{ }
}
}
private void SendDatas(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
List<byte[]> Datalist = e.Argument as List<byte[]>;
int l = 6;
for (int i = 0; i < Datalist.Count; i++)
{
if (bw.CancellationPending)
{
e.Cancel = true;
break;
}
//byte[] FeedBackFrameDataSend = Contracts.Encrypt(Contracts.GetSendFrame(Contracts.GetSendCmdData(Datalist[i], Contracts.Equipment)), _TransmitKey);///组装加密
byte[] FeedBackFrameDataSend = Contracts.GetSendFrame(Contracts.GetSendCmdData(Datalist[i], Contracts.Equipment));//组装
WriteLog("待发送报文:" + BitConverter.ToString(FeedBackFrameDataSend));
SocketError Error;
_Client.Client.Send(FeedBackFrameDataSend, 0, FeedBackFrameDataSend.Length, SocketFlags.None, out Error);
if (Error == SocketError.Success)
{
WriteLog("发送成功!");
}
else
{
i--;
if (l < 0)
break;
l--;
WriteLog("发送失败,即将重发,剩余" + l + "次!");
}
}
}
public void ClientServiceStart()
{
if (!_Client.Connected)
{
WriteLog("连接中断,即将重启1");
return;
}
NetworkStream NWstm = _Client.GetStream();
while (true)
{
if (!_Client.Connected)
{
WriteLog("连接中断,即将重启2");
break;
}
try
{
int firstByte = -1;
int SecondByte = -1;
int thirdByte = -1;
int FourByte = -1;
bool IsTrue = false;
string errorCmd = string.Empty;
while ((firstByte = NWstm.ReadByte()) != -1)
{
if (firstByte == Contracts.ReportHead[0])
{
SecondByte = NWstm.ReadByte();
if (SecondByte != Contracts.ReportHead[1])
{
errorCmd += Convert.ToString(firstByte, 16) + "-" + Convert.ToString(SecondByte, 16) + "-";
break;
}
thirdByte = NWstm.ReadByte();
if (thirdByte != Contracts.ReportHead[2])
{
errorCmd += Convert.ToString(firstByte, 16) + "-" + Convert.ToString(SecondByte, 16) + "-" + Convert.ToString(thirdByte, 16) + "-";
break;
}
FourByte = NWstm.ReadByte();
if (FourByte != Contracts.ReportHead[3])
{
errorCmd += Convert.ToString(firstByte, 16) + "-" + Convert.ToString(SecondByte, 16) + "-" + Convert.ToString(thirdByte, 16) + "-" + Convert.ToString(FourByte, 16)+"-";
break;
}
IsTrue = true;
break;
}
else
{
errorCmd += Convert.ToString(firstByte, 16) + "-";
}
}
if (!IsTrue){
if (!string.IsNullOrEmpty(errorCmd))
WriteLog("无效报文:" + (errorCmd.Length > 0 ? errorCmd.TrimEnd('-') : errorCmd));
continue;
}
WriteLog("***************************************************************************");
_LastDatetime = DateTime.Now;
报文长度
int DgramLength = NWstm.ReadByte() * 256;
DgramLength = DgramLength + NWstm.ReadByte();
报文数据
byte[] FrameDataDecrp = new byte[DgramLength];
NWstm.Read(FrameDataDecrp, 0, DgramLength);
WriteLog("有效报文:" + BitConverter.ToString(FrameDataDecrp));
//拆装解密
//byte[] FrameData = Contracts.GetReceiveDataGram(Contracts.Decrypt(Contracts.GetSendFrame(FrameDataDecrp), _TransmitKey));
拆装
//byte[] FrameData = Contracts.GetReceiveDataGram(Contracts.GetSendFrame(FrameDataDecrp));
byte[] FrameData = FrameDataDecrp;
CRC验证之前(包含)的错误是致命错误不可修复,忽略处理
if (Contracts.CRC16Check(FrameData))
{
WriteLog("通过CRC校验");
设备属性检查
if (FrameData[0] == Contracts.Equipment)
{
while (m_SendDatas.IsBusy) //保证只有一个线程发送数据.避免旧的数据影响新的命令
{
m_SendDatas.CancelAsync();
Thread.Sleep(2);
}
//将数据传递给数据处理类,返回处理结果
List<byte[]> FeedBackFrameList = NetDataProcess.CmdProccess(Contracts.GetSendFrame(FrameData));
m_SendDatas.RunWorkerAsync(FeedBackFrameList); //异步发送不带TPDU数据,避免发送数据时接收不了新命令
}
else
{
while (m_SendDatas.IsBusy) //清空服务器回送数据
{
m_SendDatas.CancelAsync();
Thread.Sleep(2);
}
}
}
else { WriteLog("未通过校验"); }
}
catch (SocketException)
{
try
{
WriteLog("出现Socket异常,连接已断开");
_Client.Client.Shutdown(SocketShutdown.Both);
_Client.Client.Close();
_Client.Close();
}
catch { }
break;
}
catch
{
WriteLog("出现其他异常,连接已断开");
continue;
}
}
}
}
数据处理类
/// <summary>
/// 处理网络数据,验证接收到的数据是否正确
/// </summary>
public static class NetDataProcess
{
private static string _reportHead = "A55ACBBC";
private static byte[] _key = new byte[8] { Convert.ToByte(0xea), Convert.ToByte(0xb8)};
/// <summary>
/// PDA业务处理程序
/// </summary>
/// <param name="CmdData">命令字和数据</param>
/// <param name="ClientType">客户端类型:1浏览器本地,2 TCP远程</param>
public static List<byte[]> CmdProccess(byte[] _DBuf)
{
List<byte[]> FeedBackData = new List<byte[]>();
DataProcess dp = null;
switch ((int)_DBuf[7])
{
case (int)NetCmdType.报文错误: /错误报文不处理
WriteLog("报文错误");
break;
case (int)NetCmdType.用户登录请求:
dp = new UserLogin();
break;
default:
WriteLog("不支持的命令字" + _DBuf[7].ToString("x2"));
break;
}
if (dp != null)
{
dp._rbuf = _DBuf;
dp.StartProcess("");
if (dp.Sendbuf == null)
WriteLog("发送数据报文为空,请检查");
if (!string.IsNullOrEmpty(dp._ErrorMsg))
{
WriteLog(dp._ErrorMsg);
}
FeedBackData.Add(dp.Sendbuf);
}
return FeedBackData;
}
private static void WriteLog(string msg)
{
try
{
WritLogFile.Log.WriteFile(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff-->") + msg);
}
catch
{ }
}
}
版权声明:本文为wuyajungogo原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。