TcpClient

TcpClient
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

}
View Code

TcpClient

 

上一篇:Socket之异步TCP客户端断线重连


下一篇:Tcp连接方式