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<String> CmdQueue { get; set; } public event EventHandler<ReceivedEventArgs> 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 /// <summary> /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed /// and unmanaged resources; <c>false</c> /// to release only unmanaged resources. /// </param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { try { Stop(); } catch { } } disposed = true; } } #endregion #region Help Method /// <summary> /// 毫秒为单位 /// </summary> /// <param name="socket"></param> /// <param name="time"></param> /// <param name="interval"></param> 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 /// <summary> /// 获取的有效桢信息 /// </summary> public class GatherDataInfo { public String GroupId { get; set; } public DateTime? AddTime { get; set; } /// <summary> /// 字节信息 /// </summary> public String RawStr { get; set; } /// <summary> /// 转化后的信息 /// </summary> public string StrValue { get; set; } /// <summary> /// 1,有效果 /// 0,无效 /// </summary> public int Status { get; set; } /// <summary> /// G:毛重,T=皮重,NET=净重 /// </summary> public String Legend { get; set; } } #endregion #region Log public class LogUtil { //public static void LogInfo(ElecScale_Log ent) //{ // if (!SimpleCfgMgr.GetV<bool>("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<bool>("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 }