using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Diagnostics;
using F.Studio.Common.Cfg;
using System.Collections.Concurrent;
namespace EC.UI
{
public class TCPMonitor:IDisposable
{
public String IP { get; set; }
public int Port { get; set; } //7788
public ConcurrentQueue CmdQueue { get; set; }
public event EventHandler ReceivedData;
private bool IsRuning = false;
private bool Enabled = false;
private bool disposed = false;
public int _WaitSeconds = 3;
public GatherDataInfo LastGatherData { get; private set; }
public TCPMonitor(string ip, int port)
{
this.IP = ip;
this.Port = port;
LastGatherData = new GatherDataInfo() { Status = 0 };
CmdQueue = new ConcurrentQueue<string>();
}
public void Start()
{
if (IsRuning) return;
Enabled = true;
IsRuning = true;
ThreadPool.QueueUserWorkItem((o) => { _Start(); });
}
public void SendCmd(string cmd)
{
CmdQueue.Enqueue(cmd);
#region
//if (!Enabled) return;
//using (TcpClient tcpClient = new TcpClient())
//{
// NetworkStream stream = null;
// try
// {
// tcpClient.Connect(IP, Port);
// stream = tcpClient.GetStream();
// stream.ReadTimeout = 1000 * 30;//30秒读超时
// var cmdStr=cmd;
// var cmdBytes = Encoding.UTF8.GetBytes(cmdStr);
// stream.Write(cmdBytes, 0, cmdBytes.Length);
// LogInfo("发送指令:" + cmdStr);
// LogInfo(string.Format("开始{0}秒等待...",_WaitSeconds));
// Thread.Sleep(1000 * _WaitSeconds);
// LogInfo("开始读返回数据,超时:30秒");
// Byte[] buffer = new byte[1024];
// StringBuilder sb = new StringBuilder();
// var len = 0;
// try
// {
// len = stream.Read(buffer, 0, buffer.Length);
// while (len > 0)
// {
// var strData = Encoding.UTF8.GetString(buffer, 0, len);
// sb.Append(strData);
// LogInfo("Data:" + strData.TrimEnd("\r\n".ToCharArray()) + " Len:" + len);
// if (strData.IndexOf("Result:") > 0)
// {
// break;
// }
// len = stream.Read(buffer, 0, buffer.Length);
// }
// }
// catch (Exception ex) { Console.WriteLine("读数据:" + ex.Message); }
// #region 解析数据
// if (sb.Length>=10)
// {
// var strData = sb.ToString();
// var index=strData.IndexOf("Result:");
// if (strData.StartsWith("Check:", StringComparison.OrdinalIgnoreCase) && index> 0)
// {
// var data = strData.Substring(6,index-6);
// var arr = data.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
// if (arr.Length == 3)
// {
// var pass = arr[2].StartsWith("OK", StringComparison.OrdinalIgnoreCase);
// if (ReceivedData != null && pass)
// {
// ReceivedData(this, new ReceivedEventArgs() { Cmd = -1, MNo = arr[0] });
// }
// }
// }
// }
// #endregion
// }
// catch (Exception ex)
// {
// LogErr(ex);
// throw ex;
// }
// finally
// {
// IsRuning = false;
// try { stream.Close(); }
// catch { }
// try { tcpClient.Close(); }
// catch { }
// LogInfo("完成本次通讯:" + Thread.CurrentThread.ManagedThreadId);
// }
//}
#endregion
}
private void _Start()
{
// return;//目前不使用
LogInfo("进入工作线程:" + Thread.CurrentThread.ManagedThreadId);
using (TcpClient tcpClient = new TcpClient())
{
NetworkStream stream=null;
try
{
tcpClient.Connect(IP, Port);
SetKeepAlive(tcpClient.Client, 1000 * 30, 1000);//无数据传输后30秒发起心跳检测,每1秒进行一次,5次失败后streamRead将报错
stream = tcpClient.GetStream();
stream.ReadTimeout = 1000 * 30;//30秒读超时
#region 发送指令 让电子秤每秒发送一次
//var cmd = "CP\r\n1P\r\n";
//var cmdBytes = Encoding.Default.GetBytes(cmd);
//stream.Write(cmdBytes, 0, cmdBytes.Length);
#endregion
Byte[] buffer = new byte[1024];
int errCount = 0;
StringBuilder sb = new StringBuilder();
#region 循环检测
DateTime lastSendTime = DateTime.Now;
while (Enabled)
{
try
{
if ((DateTime.Now - lastSendTime).TotalSeconds > 30)
{
CmdQueue.Enqueue("$Ping$:" + DateTime.Now.Ticks + "$End$");
}
#region 线发送指令
if (CmdQueue.Count > 0)
{
var cmdStr="";
if (CmdQueue.TryDequeue(out cmdStr))
{
var cmdBytes = Encoding.UTF8.GetBytes(cmdStr);
stream.Write(cmdBytes, 0, cmdBytes.Length);
LogInfo("发送指令:" + cmdStr);
lastSendTime = DateTime.Now;
}
}
#endregion
if (!tcpClient.Connected)
{
//完全没鸟用
throw new Exception("tcpClient.Connected==false链接断开了!");
}
if (stream.DataAvailable)
{
var len = stream.Read(buffer, 0, buffer.Length);
var rStr = Encoding.Default.GetString(buffer, 0, len);
var checkIndex = rStr.IndexOf("Check:");
if (checkIndex > 0)
{
rStr = rStr.Substring(checkIndex);
}
sb.Append(rStr);
LogInfo("Data:" + rStr.TrimEnd("\r\n".ToCharArray()) + " Len:" + len);
#region 尝试解析数据
if (sb.Length >= 10)
{
var strData = sb.ToString();
if (strData.StartsWith("Check:", StringComparison.OrdinalIgnoreCase) )
{
var index = strData.IndexOf("Result:");
if (index > 0)
{
var data = strData.Substring(6, index - 6);
var arr = data.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (arr.Length == 3)
{
var pass = arr[2].StartsWith("OK", StringComparison.OrdinalIgnoreCase);
sb.Clear();//清空缓存
if (ReceivedData != null && pass)
{
ReceivedData(this, new ReceivedEventArgs() { Cmd = -1, MNo = arr[0] });
}
}
else
{
sb.Clear();
}
}
}
else
{
sb.Clear();
}
}
#endregion
if (sb.Length > 1000)
{
sb = new StringBuilder();
}
}
Thread.Sleep(200);
errCount = 0;
}
catch (Exception ex)
{
errCount++;
if (errCount >= 3)
{
throw;
}
LogErr(ex);
Thread.Sleep(1000 * 3);
}
}
#endregion
}
catch (Exception ex)
{
LogErr(ex);
// throw ex;
}
finally
{
try{stream.Close();} catch { }
try { tcpClient.Close(); }catch { }
IsRuning = false;
if (Enabled)
{
IsRuning = true;
ThreadPool.QueueUserWorkItem((o) => { _Start(); });
}
LogInfo("退出工作线程:" + Thread.CurrentThread.ManagedThreadId);
}
}
}
private void LogErr(Exception ex)
{
//LogUtil.LogErr(new ElecScale_Log { Err = ex,Flag=IP,LogType="错误" });
if (!string.IsNullOrWhiteSpace(ex.Message))
{
Console.WriteLine(ex.Message);
}
}
private void LogInfo(string msg)
{
//LogUtil.LogInfo(new ElecScale_Log { Msg =msg,Flag=IP,LogType="消息" });
Console.WriteLine(msg);
}
public void Stop()
{
Enabled = false;
}
#region IDisposable Members
///
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed
/// and unmanaged resources; false
/// to release only unmanaged resources.
///
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
try
{
Stop();
}
catch
{
}
}
disposed = true;
}
}
#endregion
#region Help Method
///
/// 毫秒为单位
///
///
///
///
private void SetKeepAlive(Socket socket, ulong time, ulong interval)
{
try
{
byte[] optionInValue = new byte[12];
ulong[] numArray = new ulong[3];
if (time == 0 || interval == 0)
numArray[0] = 0;
else
numArray[0] = 1;
numArray[1] = time;
numArray[2] = interval;
for (int i = 0; i < numArray.Length; i++)
{
optionInValue[i * 4 + 3] = (byte)(numArray[i] >> 0x18 & 0xff);
optionInValue[i * 4 + 2] = (byte)(numArray[i] >> 0x10 & 0xff);
optionInValue[i * 4 + 1] = (byte)(numArray[i] >> 8 & 0xff);
optionInValue[i * 4] = (byte)(numArray[i] & 0xff);
}
byte[] bytes = BitConverter.GetBytes(0);
socket.IOControl(IOControlCode.KeepAliveValues, optionInValue, bytes);
}
catch (Exception exception)
{
Console.WriteLine("设置KeepAlive错误:" + exception.Message);
}
}
#endregion
}
#region Model
///
/// 获取的有效桢信息
///
public class GatherDataInfo
{
public String GroupId { get; set; }
public DateTime? AddTime { get; set; }
///
/// 字节信息
///
public String RawStr { get; set; }
///
/// 转化后的信息
///
public string StrValue { get; set; }
///
/// 1,有效果
/// 0,无效
///
public int Status { get; set; }
///
/// G:毛重,T=皮重,NET=净重
///
public String Legend { get; set; }
}
#endregion
#region Log
public class LogUtil
{
//public static void LogInfo(ElecScale_Log ent)
//{
// if (!SimpleCfgMgr.GetV("LogInfo", false)) return;
// Console.WriteLine(ent.Msg);
// StackFrame sf = new StackFrame(1);
// var methodInfo = sf.GetMethod();
// if (methodInfo.Name == "LogInfo")
// {
// methodInfo = new StackFrame(2).GetMethod();
// }
// var fname = methodInfo.DeclaringType.FullName + "->" + methodInfo.Name;
// Action act = () =>
// {
// using (var ctx = DBCtx.GetCtx())
// {
// try
// {
// var logEntry = new ElecScale_Log();
// logEntry.LogType = ent.LogType;
// logEntry.AddTime = DateTime.Now;
// logEntry.CodeSoure = fname;
// logEntry.Msg = ent.Msg;
// logEntry.Flag = ent.Flag;
// ctx.ElecScale_Log.AddObject(logEntry);
// ctx.SaveChanges();
// }
// catch { }
// }
// };
// act.BeginInvoke(null, null);
//}
//public static void LogErr(ElecScale_Log ent)
//{
// if (!SimpleCfgMgr.GetV("LogErr", false)) return;
// Console.WriteLine(ent.Err.Message);
// StackFrame sf = new StackFrame(1);
// var methodInfo = sf.GetMethod();
// if (methodInfo.Name == "LogErr")
// {
// methodInfo = new StackFrame(2).GetMethod();
// }
// var fname = methodInfo.DeclaringType.FullName + "->" + methodInfo.Name;
// Action act = () =>
// {
// using (var ctx = DBCtx.GetCtx())
// {
// try
// {
// var logEntry = new ElecScale_Log();
// logEntry.LogType = "错误";
// logEntry.AddTime = DateTime.Now;
// logEntry.CodeSoure = fname;
// logEntry.Msg = ent.Err.ToString();
// logEntry.Flag = ent.Flag;
// ctx.ElecScale_Log.AddObject(logEntry);
// ctx.SaveChanges();
// }
// catch { }
// }
// };
// act.BeginInvoke(null, null);
//}
}
#endregion
}