using DataEntity.Sockets.Base; using HxEnum; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.Threading; using XCommon; using XCommon.Log; using XImagingXhandler.XDAL; using static HxEnum.StateEnum; namespace HxSocketImplement.Sockets { /// /// Socket服务 /// public class HxSockServiceExecute { #region 变量 /// /// 缓存参数 /// public static Dictionary CacheSocketParameterData = new Dictionary(); /// /// 监测心跳Thread /// private static Thread checkHeartbeatThread = null; /// /// 接收消息Thread /// private static Thread getReceiveThread = null; #endregion #region 获取指定设备类型缓存数据 /// /// 获取指定设备类型缓存数据 /// /// 类型 /// IP /// 端口 /// 设备ID /// public static SocketParameterModel GetSocketParameterModel(string equipmentType, string ip, int port, string equipmentId) { if (!string.IsNullOrWhiteSpace(equipmentType)) { var cacheSocketParameterData = CacheSocketParameterData.Where(x => x.Key == equipmentType + ip + port + equipmentId); if (cacheSocketParameterData != null && cacheSocketParameterData.Count() > 0) { return cacheSocketParameterData.FirstOrDefault().Value; } } return null; } #endregion #region 连接+断开+检查心跳 #region 连接服务端 /// /// 连接服务端 /// /// 类型 /// IP /// 端口 /// 设备ID /// public static bool Connect(string equipmentType, string ip, int port, string equipmentId) { var socketParameterModel = GetSocketParameterModel(equipmentType, ip, port, equipmentId); try { if (socketParameterModel != null && socketParameterModel.Socket == null) { #region 建立连接 bool isConnect = ConnectSocket(socketParameterModel); #endregion #region 监测心跳 checkHeartbeatThread = new Thread(() => CheckHeartbeat(socketParameterModel)); checkHeartbeatThread.IsBackground = true; checkHeartbeatThread.Start(); #endregion #region 接收消息Thread getReceiveThread = new Thread(() => GetReceive(socketParameterModel)); getReceiveThread.IsBackground = true; getReceiveThread.Start(); #endregion if (isConnect) { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "连接服务器【成功】Connect"); } else { return false; } } else { if (CheckConnected(socketParameterModel.Socket, socketParameterModel.Ip) == false) { bool isConnect = ConnectSocket(socketParameterModel); if (isConnect) { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "连接服务器【成功】Connect"); } else { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "连接服务器【失败】Connect"); return false; } } else { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "连接服务器【成功】Connect"); } } } catch (Exception ex) { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "连接服务器【失败】Connect" + ex.Message); return false; } return true; } #endregion #region 建立连接 /// /// 建立连接 /// /// /// public static bool ConnectSocket(SocketParameterModel socketParameterModel) { try { #region 建立连接 socketParameterModel.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //1.0 实例化套接字(IP4寻址地址,流式传输,TCP协议) IPAddress address = IPAddress.Parse(socketParameterModel.Ip); //2.0 创建IP对象 IPEndPoint endPoint = new IPEndPoint(address, socketParameterModel.Port); //3.0 创建网络端口包括ip和端口 socketParameterModel.Socket.Connect(endPoint); //4.0 建立连接 #endregion return true; } catch (Exception ex) { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "连接服务器【失败】ConnectSocket" + ex.Message); } return false; } #endregion #region 断开连接 /// /// 断开连接 /// /// 类型 /// IP /// 端口 /// 设备ID /// public static bool BreakConnect(string equipmentType, string ip, int port, string equipmentId) { var socketParameterModel = GetSocketParameterModel(equipmentType, ip, port, equipmentId); if (socketParameterModel != null && socketParameterModel.Socket != null && socketParameterModel.Socket.Connected) { // 断开与服务端的连接时,监测心跳Thread和接收消息Thread也要关闭 if (checkHeartbeatThread != null) { checkHeartbeatThread.Abort(); checkHeartbeatThread = null; } if (getReceiveThread != null) { getReceiveThread.Abort(); getReceiveThread = null; } socketParameterModel.Socket.Shutdown(SocketShutdown.Both); socketParameterModel.Socket.Close(); socketParameterModel.Socket.Dispose(); LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "断开连接【成功】BreakConnect"); socketParameterModel.Socket = null; socketParameterModel = null; //Thread.Sleep(500); return true; } else { LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "断开连接【失败】BreakConnect"); } return false; } #endregion #region 检查心跳 /// /// 检查心跳 /// /// public static bool CheckHeartbeat(SocketParameterModel model) { while (true) { try { if (CheckConnected(model.Socket, model.Ip)) { string msgId = $"{model.Ip}_{model.Port}_{model.EquipmentId}_{model.EquipmentType}_{HxSockServiceExecute.InstrunctionId()}"; HeartbeatMoel heartbeatMoel = new HeartbeatMoel { message_id = msgId,// + "_" + HxSockServiceExecute.InstrunctionId(), message_type = model.HeartMessageType, equipment_id = model.HeartEquipmentId, workflow_id = "workflow_id_" + msgId, equipment_status = 1, actual_device_status = 1, connected = 1, timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }; string sendJson = JsonConvert.SerializeObject(heartbeatMoel) + model.SpecifiedDisplay; byte[] buffer = new byte[2048]; buffer = Encoding.UTF8.GetBytes(sendJson); int receive = model.Socket.Send(buffer); } else { #region 建立连接 model.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //1.0 实例化套接字(IP4寻址地址,流式传输,TCP协议) IPAddress address = IPAddress.Parse(model.Ip); //2.0 创建IP对象 IPEndPoint endPoint = new IPEndPoint(address, model.Port); //3.0 创建网络端口包括ip和端口 model.Socket.Connect(endPoint); //4.0 建立连接 #endregion } } catch (Exception ex) { LoggerSocketHelper.DebugLog(GetIpInfo(model) + "检查心跳【错误】CheckHeartbeat" + ex.Message); } Thread.Sleep(5000); } } #endregion #endregion #region 判断SOCKET是否连接 #region 检查连接是否断开 /// /// 检查连接是否断开 /// /// public static bool CheckConnected(Socket socket, string ip) { if (socket != null && socket.Connected && PingOC(ip) && ComUtility.IsSocketConnected(socket)) { return true; } return false; } #endregion #region 检查一个Socket是否可连接(PING网络是否通) /// /// 检查一个Socket是否可连接(PING网络是否通) /// /// /// public static bool PingOC(String ips) { return true; //bool ret; //Process p = new Process(); //p.StartInfo.FileName = "cmd.exe"; //p.StartInfo.UseShellExecute = false; //p.StartInfo.RedirectStandardInput = true; //p.StartInfo.RedirectStandardOutput = true; //p.StartInfo.RedirectStandardError = true; //p.StartInfo.CreateNoWindow = true; //int i = 0; //p.Start(); //p.StandardInput.WriteLine("ping -n 1 " + ips); //p.StandardInput.WriteLine("exit"); //string strRst = p.StandardOutput.ReadToEnd(); //if (strRst.IndexOf("(100%") == -1) //{ // ret = true; //} //else //{ // ret = false; //} //p.Close(); //return ret; } #endregion #endregion #region 发送和接收数据 #region 发送数据 /// /// 发送数据 /// /// 设备类别 /// IP /// 端口 /// 设备ID /// JSON参数据 /// 工作流ID /// public static Result SendData(string equipmentType, string ip, int port, string equipmentId, string data, string workflow_id) { Result result = new Result(); var socketParameterModel = GetSocketParameterModel(equipmentType, ip, port, equipmentId); if (socketParameterModel != null) { if (CheckConnected(socketParameterModel.Socket, socketParameterModel.Ip)) { bool blockingState = socketParameterModel.Socket.Blocking; try { #region 数据分割 //int strLength = data.Length; //int byteLength = 10; //if (strLength > byteLength) //{ // double loopNumTemp = (double)(Math.Round((decimal)(Convert.ToDecimal(strLength) / Convert.ToDecimal(byteLength)), 5)); // var loopData = WebHelper.GetStr(data, byteLength); // int loopNum = 1000; // foreach (var item in loopData) // { // string loopStr = item; // if (loopNum == loopData.Count()) // { // loopStr = loopStr + socketParameterModel.SpecifiedDisplay; // } // //string sendMessage = data + socketParameterModel.SpecifiedDisplay; // socketParameterModel.Socket.Send(Encoding.UTF8.GetBytes(loopStr)); // LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "发送数据【成功】SendData:" + loopStr); // loopNum = loopNum + 1; // Thread.Sleep(2000); // } //} //else //{ // string sendMessage = data + socketParameterModel.SpecifiedDisplay; // socketParameterModel.Socket.Send(Encoding.UTF8.GetBytes(sendMessage)); // LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "发送数据【成功】SendData:" + sendMessage); //} string sendMessage = data + socketParameterModel.SpecifiedDisplay; //Thread.Sleep(100); var sendNum = socketParameterModel.Socket.Send(Encoding.UTF8.GetBytes(sendMessage)); LoggerSocketHelper.DebugLog(GetIpInfo(socketParameterModel) + "发送数据【成功】SendData:" + sendMessage + "_sendNum:" + sendNum + "_本地端口号:" + socketParameterModel.Socket.LocalEndPoint); #endregion result = GetReceiveResult(socketParameterModel, workflow_id); return result; } catch (Exception ex) { result.status = StateEnum_Equipment.Failed; result.msg = GetIpInfo(socketParameterModel) + "发送数据【出错】SendData:" + ex.Message + ",StackTrace:" + ex.StackTrace; LoggerSocketHelper.DebugLog(result.msg + ex); return result; } //finally //{ // _socket.Blocking = blockingState; // 恢复状态 //} } else { result.status = StateEnum_Equipment.Failed; result.msg = $"发送数据【出错】SendData:设备ID:{equipmentType},{ip}:{port},{equipmentId}已断开连接"; LoggerSocketHelper.DebugLog(result.msg); return result; } } result.status = StateEnum_Equipment.Failed; result.msg = $"发送数据【出错】SendData:未获取到缓存里面的{equipmentType}数据"; return result; } #endregion #region 获取返回数据-实际结果 /// /// 获取返回数据-实际结果 /// /// 发送指令工作流ID /// public static Result GetReceiveResult(SocketParameterModel model, string workflow_id) { Result rModel = new Result(); while (true) { if (model.cacheReceiveData != null && model.cacheReceiveData.Count > 0) { CacheReceiveDataModel tempData = new CacheReceiveDataModel(); for (int i = 0; i < model.cacheReceiveData.Count; i++) { if (model.cacheReceiveData[i] != null && model.cacheReceiveData[i].CacheKey == workflow_id) { tempData = model.cacheReceiveData[i]; break; } } if (tempData != null && !string.IsNullOrWhiteSpace(tempData.CacheKey) && tempData.CacheValue != null) { ResponseObject roData = tempData.CacheValue; if (roData != null && roData.workflow_id == workflow_id) { string tempRoData = JsonConvert.SerializeObject(roData); switch (roData.method_status) { case 2: rModel.status = StateEnum_Equipment.Completed; rModel.msg = "执行成功"; rModel.data = new Data { json = tempRoData }; break; case 3: rModel.status = StateEnum_Equipment.Failed; rModel.msg = "执行失败,错误码:" + roData.error.error_code + ",错误内容:" + roData.error.error_text; rModel.data = new Data { json = tempRoData }; rModel.DealWithType = EnumManagement.GetEnumValue(DealWithType_Enum.DealWithTypeBEnum).ToString(); if (roData != null && roData.error != null) { rModel.ErrorMsg = new ErrorMsgModel { Error_Code = roData.error.error_code, Error_Text = roData.error.error_text, Troubleshoot = roData.error.troubleshoot }; rModel.DealWithType = roData.error.dealwithtype != null ? roData.error.dealwithtype.ToString() : EnumManagement.GetEnumValue(DealWithType_Enum.DealWithTypeBEnum).ToString(); } break; case 4: rModel.status = StateEnum_Equipment.Canceled; rModel.msg = "任务被取消"; rModel.data = new Data { json = tempRoData }; break; case 5: rModel.status = StateEnum_Equipment.AlarmInfo; rModel.msg = "告警信息,错误码:" + roData.error.error_code + ",错误内容:" + roData.error.error_text; rModel.data = new Data { json = tempRoData }; rModel.DealWithType = EnumManagement.GetEnumValue(DealWithType_Enum.DealWithTypeBEnum).ToString(); if (roData != null && roData.error != null) { rModel.ErrorMsg = new ErrorMsgModel { Error_Code = roData.error.error_code, Error_Text = roData.error.error_text, Troubleshoot = roData.error.troubleshoot }; rModel.DealWithType = roData.error.dealwithtype != null ? roData.error.dealwithtype.ToString() : EnumManagement.GetEnumValue(DealWithType_Enum.DealWithTypeBEnum).ToString(); } break; default: rModel.status = EnumManagement.GetField(roData.method_status); rModel.msg = "返回出错"; rModel.data = new Data { json = tempRoData }; break; } LoggerSocketHelper.DebugLog(GetIpInfo(model) + $"获取返回数据【{rModel.msg},{rModel.status}】GetReceiveResult" + JsonConvert.SerializeObject(rModel)); return rModel; } //else //{ // LoggerSocketHelper.DebugLog(GetIpInfo() + "获取返回数据【出错】GetReceive"); //} } } Thread.Sleep(100); } } #endregion #region 获取返回数据-sock结果 /// /// 获取返回数据-sock结果 /// /// /// /// public static Result GetReceive(SocketParameterModel model) { Result rModel = new Result(); while (true) { try { bool isCheckConnected = CheckConnected(model.Socket, model.Ip); //if (model.Socket.Available > 0 ) //{ // LoggerSocketHelper.DebugLog("连接状态:" + isCheckConnected + "_IP:" + model.Ip +"_端口:"+ model.Port + "_Available数据量:" + model.Socket.Available); //} if (isCheckConnected) { if (model.Socket.Available > 0) { lock (model.LockReceive) { int length = model.Socket.Receive(model.Buffer); if (length > 0 && model.Socket.Connected) { var resultMsg = Encoding.UTF8.GetString(model.Buffer, 0, length); if (resultMsg.Contains(model.SpecifiedDisplay) == false) //如果结尾没有指定符号,继续获取 { StringBuilder sb = new StringBuilder(); sb.Append(resultMsg); while (sb.ToString().Contains(model.SpecifiedDisplay) == false) { model.Socket.Blocking = true; int tempLength = model.Socket.Receive(model.Buffer); if (tempLength > 0 && model.Socket.Connected) { var tempStr = Encoding.UTF8.GetString(model.Buffer, 0, tempLength); sb.Append(tempStr); } } IsLoop(model, sb.ToString()); } else { IsLoop(model, resultMsg); } } } } } } catch (Exception ex) { rModel.status = StateEnum_Equipment.Failed; rModel.msg = GetIpInfo(model) + "获取返回数据【缓存失败】GetReceive:" + ex.Message; LoggerSocketHelper.DebugLog(rModel.msg + ex); } } //return rModel; } /// /// 是否循环数据 /// /// /// private static void IsLoop(SocketParameterModel model, string resultMsg) { if (!string.IsNullOrWhiteSpace(resultMsg) && resultMsg.Contains("error")) { string[] sArray = Regex.Split(resultMsg, model.SpecifiedDisplay, RegexOptions.IgnoreCase); if (sArray != null && sArray.Count() > 0) { //var resultMsgBysArray = sArray.FirstOrDefault(m => m.Contains("error")); foreach (var resultMsgBysArray in sArray) { var isError = resultMsgBysArray.Contains("error"); if (isError && !string.IsNullOrWhiteSpace(resultMsgBysArray)) { Thread.Sleep(400); ResponseObject roData = JsonConvert.DeserializeObject(resultMsgBysArray); try { #region 插入数据到缓存中 不能插入相同值 if (model.cacheReceiveData != null && model.cacheReceiveData.Count > 0) { object isLockAdd = new object(); lock (isLockAdd) { bool isHaveValue = false; for (int i = 0; i < model.cacheReceiveData.Count; i++) { if (model.cacheReceiveData[i].CacheKey == roData.workflow_id) { isHaveValue = true; break; } } if (isHaveValue == false) { model.cacheReceiveData.Add(new CacheReceiveDataModel { CacheKey = roData.workflow_id, CacheValue = roData }); } } } else { model.cacheReceiveData.Add(new CacheReceiveDataModel { CacheKey = roData.workflow_id, CacheValue = roData }); } #endregion LoggerSocketHelper.DebugLog(GetIpInfo(model) + "获取返回数据【缓存成功】IsLoop:" + resultMsg); } catch (Exception ex) { LoggerSocketHelper.DebugLog(GetIpInfo(model) + "获取返回数据【缓存失败】IsLoop:" + resultMsg + "失败错误内容:" + ex.Message + ex); } } } } } //驱动返回心跳 else if (resultMsg.Contains("equipment_status") && resultMsg.Contains("connected")) { if (resultMsg.Contains(model.SpecifiedDisplay)) { var data = JObject.Parse(resultMsg.Replace(model.SpecifiedDisplay, "")); //获取设备ID string equipmentId = model.EquipmentType + model.Ip + model.Port + model.EquipmentId; //string equipmentId = model.EquipmentId;// data["equipment_id"].ToString(); #region 设备状态(0驱动虚拟机模式,1驱动连真机状态) bool isEquipped = data["connected"].ToString() != "0"; //设备是否存在字典中 if (SocketParameterModel.Dic_EquipmentConnectedStatus != null && SocketParameterModel.Dic_EquipmentConnectedStatus.Count > 0) { for (int i = 0; i < SocketParameterModel.Dic_EquipmentConnectedStatus.Count; i++) { var dicEcs = SocketParameterModel.Dic_EquipmentConnectedStatus.ElementAt(i); if (dicEcs.Key == equipmentId) { //更新驱动连接设备状态 SocketParameterModel.Dic_EquipmentConnectedStatus[equipmentId] = isEquipped; } } } else { //增加驱动连接设备状态 SocketParameterModel.Dic_EquipmentConnectedStatus.Add(equipmentId, isEquipped); } ////设备是否存在字典中 //if (SocketParameterModel.Dic_EquipmentConnectedStatus.Where(m => m.Key.Equals(equipmentId)).Count() > 0) //{ // //更新驱动连接设备状态 // SocketParameterModel.Dic_EquipmentConnectedStatus[equipmentId] = isEquipped; //} //else //{ // //增加驱动连接设备状态 // SocketParameterModel.Dic_EquipmentConnectedStatus.Add(equipmentId, isEquipped); //} #endregion #region 设备状态(是否忙碌 1空闲、2忙碌) string equipmentStatus = data["equipment_status"].ToString() == "1" ? "空闲" : (data["equipment_status"].ToString() == "2" ? "忙碌" : "出错"); if (SocketParameterModel.Dic_EquipmentStatus != null && SocketParameterModel.Dic_EquipmentStatus.Count > 0) { for (int i = 0; i < SocketParameterModel.Dic_EquipmentStatus.Count; i++) { var dicEcs = SocketParameterModel.Dic_EquipmentStatus.ElementAt(i); if (dicEcs.Key == equipmentId) { //更新驱动连接设备状态 SocketParameterModel.Dic_EquipmentStatus[equipmentId] = equipmentStatus; } } } else { //增加驱动连接设备状态 SocketParameterModel.Dic_EquipmentStatus.Add(equipmentId, equipmentStatus); } ////设备是否存在字典中 //if (SocketParameterModel.Dic_EquipmentStatus.Where(m => m.Key.Equals(equipmentId)).Count() > 0) //{ // SocketParameterModel.Dic_EquipmentStatus[equipmentId] = equipmentStatus; //} //else //{ // SocketParameterModel.Dic_EquipmentStatus.Add(equipmentId, equipmentStatus); //} #endregion } } } #endregion #endregion #region 业务逻辑 #region 随机生成字符串 /// /// 随机生成字符串 /// /// public static string InstrunctionId() { Random random = new Random(); int randKey = random.Next(1000, 9999); string guidStr = Guid.NewGuid().ToString(); return DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + guidStr; } #endregion #region 获取IP信息 /// /// 获取IP信息 /// /// private static string GetIpInfo(SocketParameterModel model) { if (model == null) { return "获取socket参数为空【出错】GetIpInfo->"; } return "IP和端口:" + model.Ip + ":" + model.Port + "->"; } #endregion #endregion } }