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
}
}