using Newtonsoft.Json.Linq; using Sodao.FastSocket.Server; using Sodao.FastSocket.Server.Messaging; using Sodao.FastSocket.SocketBase; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Reflection; using XImaging.Automation.Library.HxDriverLib; using XImaging.Automation.Service.Interface; namespace XImaging.Automation.Service { class ResponseMessagePackage { public static JObject NullData { get { return JObject.FromObject(new { }); } } public static JObject FormStorageInfoData(int m_stack, int m_level, string m_barcode) { return JObject.FromObject( new { stack = m_stack, level = m_level, barcode = m_barcode }); } } public class HxTcpHandler { /// /// //主控连接句柄 /// private Dictionary m_mainConnection = new Dictionary(); private static HxTcpHandler m_instance = null; private System.Timers.Timer timer = new System.Timers.Timer(); private string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); private HxTcpHandler() { MessageSection section = ConfigurationManager.GetSection("messages") as MessageSection; if (section.Heartbeat.Enabled) { timer.Interval = 5000; timer.Elapsed += (s, e1) => { CheckConnectAlive(section.Heartbeat.Timeout); }; timer.Start(); } } private void CheckConnectAlive(int timeout) { if (m_mainConnection.Count > 0) { try { foreach (var item in m_mainConnection) { if ((DateTime.UtcNow - item.Value.LatestActiveTime).Seconds > timeout) { LogConstant.logger.Print("[CheckConnectAlive 心跳包超时]"); Discard(item.Key); } } } catch { } } } /// /// 获取实例 /// /// public static HxTcpHandler GetInstance() { if (m_instance == null) m_instance = new HxTcpHandler(); return HxTcpHandler.m_instance; } /// /// 当前是否有客户端连接 /// public bool isConnected { set; get; } /// /// 连接ID /// public bool Contains(long ConnectionID) { return this.m_mainConnection.ContainsKey(ConnectionID); } /// /// 连接地址 /// public string Address(long id) { return this.m_mainConnection[id].RemoteEndPoint.ToString(); } /// /// 保持一个新的连接 /// /// public void Hold(IConnection connection) { this.m_mainConnection.Add(connection.ConnectionID, connection); this.m_mainConnection[connection.ConnectionID].BeginReceive(); //UpdateLocalCache(); } private void UpdateLocalCache() { string remoteEPs = ""; foreach(IConnection conns in this.m_mainConnection.Values) { remoteEPs += conns.RemoteEndPoint + "\r\n"; } FileStream fs = new FileStream(Path.Combine(appPath, "biosen_conns.dat"), FileMode.Create); StreamWriter sw = new StreamWriter(fs); sw.Write(remoteEPs); sw.Flush(); sw.Close(); fs.Close(); } /// /// 断开时丢弃当前连接 /// public void Discard(long id) { this.m_mainConnection[id].BeginDisconnect(); while (this.m_mainConnection[id].Active) { System.Threading.Thread.Sleep(200); } this.m_mainConnection.Remove(id); //UpdateLocalCache(); } public static bool Empty() { return m_instance.m_mainConnection.Count == 0; } public static void ReplyHeartBeatMessage(HxMessage message, int From = 0, int simulate=0) { message.Connected = simulate; foreach (var conn in m_instance.m_mainConnection) if (From == 0 || From.Equals(conn.Value.LocalEndPoint.Port)) message.Heartbeat(conn.Value); } public static void ReplyHeartBeatGWMessage(HxMessage message, int From = 0) { foreach (var conn in m_instance.m_mainConnection) if (From == 0 || From.Equals(conn.Value.LocalEndPoint.Port)) message.HeartbeatGW(conn.Value); } public static void ReplyAckMessage(HxMessage message, int From = 0) { foreach (var conn in m_instance.m_mainConnection) { if (From == 0 || From == conn.Value.LocalEndPoint.Port) { LogConstant.logger.Print(string.Format("[Socket][Ack][{1}]回复ACK指令给{0}", conn.Value.RemoteEndPoint, message.MessageID)); message.Ack(conn.Value); } } } public static void ReplyFinishMessage(HxMessage message, JObject data, int From = 0) { foreach (var conn in m_instance.m_mainConnection) { if (From == 0 || From == conn.Value.LocalEndPoint.Port) { LogConstant.logger.Print(string.Format("[Socket][Finish][{2}]回复Finish指令给{0}, data={1}", conn.Value.RemoteEndPoint, data.ToString(), message.MessageID)); message.Finish(conn.Value, data); } } } public static void ReplyFailedMessage(HxMessage message, JObject data, string error_code, string error_text, int dealwithtype=0, int troubleshoot=7, int From = 0) { foreach (var conn in m_instance.m_mainConnection) { if (From == 0 || From == conn.Value.LocalEndPoint.Port) { LogConstant.logger.Print(string.Format("[Socket][Failed][{4}]回复Failed指令给{0}, data={1}, error_code={2}, error_text={3}", conn.Value.RemoteEndPoint, data, error_code, error_text, message.MessageID)); message.Failed(conn.Value, data, error_code, error_text, dealwithtype, troubleshoot); } } } public static void ReplyErrorMessage(HxMessage message, JObject data, string error_code, string error_text, int dealwithtype = 0, int troubleshoot=7, int From = 0) { foreach (var conn in m_instance.m_mainConnection) { if (From == 0 || From == conn.Value.LocalEndPoint.Port) { LogConstant.logger.Print(string.Format("[Socket][Error][{4}]回复Error指令给{0}, data={1}, error_code={2}, error_text={3}", conn.Value.RemoteEndPoint, data, error_code, error_text, message.MessageID)); message.Error(conn.Value, data, error_code, error_text, dealwithtype, troubleshoot); } } } } public class BiosenSocketService : AbsSocketService { /// /// Tcp连接管理 /// private HxTcpHandler m_mainTcpListener = HxTcpHandler.GetInstance(); //private IMessageQueueHandler m_handleMQ; private IMessageDispatch m_msgDispatch = MessageDispatch.GetInstance(); private string hbLogs = "false"; private bool isConnected = false; public BiosenSocketService() : base() { hbLogs = ConfigurationManager.AppSettings.Get("HBLogs"); //string mq = ConfigurationManager.ConnectionStrings["MessageQueue"].ConnectionString; //if (mq.ToLower().Equals("redis")) //{ // m_handleMQ = RedisQueueHandler.GetInstance(); //} } /// /// 连接函数 /// /// public override void OnConnected(IConnection connection) { base.OnConnected(connection); LogConstant.logger.Print("[Socket][Connection]检测到来自" + connection.RemoteEndPoint.ToString() + "的远程连接"); try { this.m_mainTcpListener.Hold(connection); LogConstant.logger.Print("[Socket][Connection]已连接" + connection.RemoteEndPoint.Address); m_msgDispatch.OnConnect(true); isConnected = true; } catch (Exception ex) { LogConstant.logger.Print("[Socket][Exception]" + ex.ToString()); } } /// /// 当连接断开时会调用此方法 /// /// /// public override void OnDisconnected(IConnection connection, Exception ex) { base.OnDisconnected(connection, ex); try { if (this.m_mainTcpListener.Contains(connection.ConnectionID)) { LogConstant.logger.Print("[Socket][Connection]即将断开连接: " + connection.RemoteEndPoint.ToString() + " ConnectionID = " + connection.ConnectionID.ToString()); this.m_mainTcpListener.Discard(connection.ConnectionID); LogConstant.logger.Print("[Socket][Connection]已断开与" + connection.RemoteEndPoint.ToString() + "的远程连接"); m_msgDispatch.OnConnect(false); isConnected = false; } } catch (Exception e) { LogConstant.logger.Print("[Socket][Exception]" + e.ToString()); } } /// /// 接收函数 /// /// /// /// public override void OnReceived(IConnection connection, HxMessage message) { try { base.OnReceived(connection, message); if (message.MessageType == HxMessage.MESSAGE_TYPE_HEARTBEAT) { //LogConstant.logger.Print(string.Format("[Socket][HeartBeat][{0}]收到来自{1}的心跳消息", message.MessageID, connection.RemoteEndPoint)); HxTcpHandler.ReplyHeartBeatMessage(message, connection.LocalEndPoint.Port); if(!isConnected) { m_msgDispatch.OnConnect(true); isConnected = true; } } else { if (message.MessageType == HxMessage.MESSAGE_TYPE_HEARTBEAT) { if(!string.IsNullOrEmpty(hbLogs) && hbLogs == "true") LogConstant.logger.Print(string.Format("[Socket][Instruction][{0}]收到来自{1}的心跳包: {2}", message.MessageID, connection.RemoteEndPoint, message.OriginJSON)); } else { LogConstant.logger.Print(string.Format("[Socket][Instruction][{0}]收到来自{1}指令消息: {2}", message.MessageID, connection.RemoteEndPoint, message.OriginJSON)); } // 向消息队列推送请求 //m_handleMQ.PushMessage(message, connection.LocalEndPoint.Port); m_msgDispatch.Parse(message); } } catch (System.Exception ex) { LogConstant.logger.Print("[Exception]" + ex.ToString()); } } /// /// 当发生错误时会调用此方法 /// /// /// public override void OnException(IConnection connection, Exception ex) { base.OnException(connection, ex); LogConstant.logger.Print("[Socket][Error]接收消息错误: " + ex.ToString()); } } }