using DataEntity.Sockets.Base;
|
using Newtonsoft.Json;
|
using Newtonsoft.Json.Linq;
|
using System;
|
using System.Collections.Generic;
|
using System.Collections.ObjectModel;
|
using System.Configuration;
|
using System.IO;
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Reflection;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using XCommon.Log;
|
using XCoreBLL;
|
using XHandler.Class.DataEx;
|
using XImagingXhandler.XDAL;
|
using static System.Net.Mime.MediaTypeNames;
|
|
namespace HxSocket
|
{
|
/// <summary>
|
/// 通讯客户端
|
/// </summary>
|
public class HxSocketClient
|
{
|
#region 变量
|
/// <summary>
|
/// 用于锁定m_listRecvMessage
|
/// </summary>
|
private object m_objListLock = new object();
|
/// <summary>
|
/// 通讯类
|
/// </summary>
|
private Socket m_socket = null;
|
private object m_socketLockObj = new object();
|
/// <summary>
|
/// 接受数据线程
|
/// </summary>
|
private Thread recvThread = null;
|
/// <summary>
|
/// 检测服务端断连定时器
|
/// </summary>
|
private System.Threading.Timer m_connectTimer = null;
|
|
/// <summary>
|
/// IP
|
/// </summary>
|
private string m_ip;
|
/// <summary>
|
/// Port
|
/// </summary>
|
private int m_port;
|
/// <summary>
|
/// 缓存所有的消息队列,同时可以收到多条消息
|
/// </summary>
|
private List<string> m_listRecvMessage = new List<string>();
|
/// <summary>
|
/// 一次拍照命令接收消息数
|
/// </summary>
|
private int m_countOfOnce = 0;
|
#endregion
|
|
#region 常量
|
public const string CMD_END = "#!HxSEP!#";
|
#endregion
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
public HxSocketClient(string ip, int port)
|
{
|
this.m_ip = ip;
|
this.m_port = port;
|
}
|
|
/// <summary>
|
/// 连接服务端
|
/// </summary>
|
/// <param name="ip"></param>
|
/// <param name="port"></param>
|
/// <returns></returns>
|
public bool connectServer(string ip, int port)
|
{
|
bool bResult = false;
|
try
|
{
|
// 创建Socket实例
|
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
// 连接服务器
|
m_socket.Connect(ip, port);
|
|
if (m_socket.Connected)
|
{
|
bResult = true;
|
LoggerSocketHelper.InfoLog(string.Format("[HxSocketClient][connectServer]: ip:{0},port:{1}连接成功!", ip, port));
|
|
StartRecvThread();
|
}
|
else
|
{
|
LoggerSocketHelper.ErrorLog(string.Format("[HxSocketClient][connectServer]: ip:{0},port:{1}连接失败!", ip, port));
|
}
|
}
|
catch (System.Net.Sockets.SocketException ex)
|
{
|
LoggerSocketHelper.ErrorLog(string.Format("[HxSocketClient][connectServer]: ip:{0},port:{1}连接失败!", ip, port));
|
}
|
finally
|
{
|
if (m_connectTimer == null)
|
{
|
// 连接离心机定时器,每500ms查看一次连接状态
|
m_connectTimer = new System.Threading.Timer(ConnectTimer, null, 0, 1000);
|
}
|
}
|
|
return bResult;
|
}
|
|
/// <summary>
|
/// 检测服务端断连定时器
|
/// </summary>
|
/// <param name="state"></param>
|
private void ConnectTimer(object state)
|
{
|
lock (m_socketLockObj)
|
{
|
try
|
{
|
// m_bIsNetConnect &&
|
if (IsConnect())
|
{
|
return;
|
}
|
|
LoggerSocketHelper.DebugLog(string.Format("[HxSocketClient]: 与ip:{0}, port:{1}断开了连接,开始重连", m_ip, m_port));
|
|
// 断开连接
|
CloseConnect();
|
|
// 关闭接受数据线程
|
CloceRecvThread();
|
|
// 连接服务端
|
connectServer(m_ip, m_port);
|
|
//m_bIsNetConnect = false;
|
//IPAddress ipAddress = IPAddress.Parse(m_strIP);
|
//LogConstant.logger.Print("开始与离心机PLC连接");
|
//m_client.Connect(ipAddress, m_nPort);
|
//// 创建一个client连接
|
//ModbusMaster = ModbusIpMaster.CreateIp(m_client);
|
//// 设置读取超时时间
|
//ModbusMaster.Transport.ReadTimeout = m_nTimeOut;
|
//ModbusMaster.Transport.WriteTimeout = m_nTimeOut;
|
//ModbusMaster.Transport.Retries = 0;
|
//LogConstant.logger.Print("离心机PLC已连接");
|
//m_bIsNetConnect = true;
|
}
|
catch (Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("ERROR:", ex);
|
|
// 断开连接
|
CloseConnect();
|
// 关闭接受数据线程
|
CloceRecvThread();
|
|
}
|
}
|
}
|
|
/// <summary>
|
/// 拍照
|
/// </summary>
|
/// <param name="data">发送的数据</param>
|
/// <param name="isOutLog">是否输出日志:心跳=false,不输出</param>
|
/// <returns></returns>
|
public List<string> SendMessage(string data, bool isOutLog = true)
|
{
|
List<string> strResult = new List<string>();
|
|
try
|
{
|
HxRequestBase reqData = JsonConvert.DeserializeObject<HxRequestBase>(data);
|
|
// 发送请求数据
|
string message = data + CMD_END;
|
byte[] msg = Encoding.ASCII.GetBytes(message);
|
if (m_socket != null && m_socket.Connected)
|
{
|
int bytesSent = m_socket.Send(msg);
|
|
if (isOutLog)
|
{
|
LoggerSocketHelper.InfoLog(string.Format("[SendMessage]:向照相系统({0})发送数据成功:{1}{2}", m_socket.RemoteEndPoint.ToString(), Environment.NewLine, message));
|
}
|
}
|
else
|
{
|
LoggerSocketHelper.InfoLog(string.Format("[SendMessage]: m_socket == null || !m_socket.Connected, 消息不发送"));
|
}
|
|
// Task、Quary
|
if (reqData.message_type == 1 ||
|
reqData.message_type == 2)
|
{
|
while (m_countOfOnce < 2)
|
{
|
Thread.Sleep(1 * 200);
|
}
|
m_countOfOnce = 0;
|
|
// 获取应答
|
for (int i = 0; i < m_listRecvMessage.Count; i++)
|
{
|
strResult.Add(m_listRecvMessage[i]);
|
}
|
m_listRecvMessage.Clear();
|
}
|
}
|
catch (Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("ERROR:", ex);
|
}
|
finally
|
{
|
//LoggerSocketHelper.InfoLog(string.Format("[SendMessage]: Finished."));
|
}
|
|
return strResult;
|
}
|
|
/// <summary>
|
/// 构建成像板位松开状态消息
|
/// </summary>
|
/// <param name="methodMsg"></param>
|
/// <param name="finished"></param>
|
/// <returns></returns>
|
public string CreateSendOpenCraw(MethodMsg methodMsg)
|
{
|
string strCommand = string.Empty;
|
string strJson = "";
|
strJson = "{" + "message_id:\"" + Guid.NewGuid().ToString() +
|
"\",message_type:" + methodMsg.methodmsg_type +
|
",method:\"" + methodMsg.methodmsg_methodname + "\"" +
|
",equipment_id:\"" + methodMsg.methodmsg_machine_id + "\"" +
|
",workflow_id:\"\"" +
|
",experiment_id:\"" + methodMsg.methodmsg_experiment_id +
|
"\",parameters:" +
|
"{" +
|
//"open:" + methodMsg.troubleshoot.ToString() + "" +
|
"}" +
|
",process_info:{}" +
|
",estimate_time:5" +
|
",timeout:60" +
|
",description:\"NO DESC\"" +
|
",timestamp:\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}";
|
|
strCommand = strJson;
|
return strCommand;
|
}
|
|
/// <summary>
|
/// 向中控发送错误或提示信息
|
/// </summary>
|
/// <param name="data">错误或提示信息字串</param>
|
/// <param name="isRemotingOper">是否中控远程</param>
|
public void sendmessageError(string data, bool isRemotingOper)
|
{
|
try
|
{
|
// 发送请求数据
|
string message = data;
|
byte[] msg = Encoding.ASCII.GetBytes(message);
|
if (isRemotingOper)
|
{
|
int bytesSent = m_socket.Send(msg);
|
LoggerSocketHelper.InfoLog("send data is successful.[data:" + message + "]");
|
}
|
}
|
catch (Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("ERROR:", ex);
|
}
|
}
|
|
public string CreateSendMsgContent(MethodMsg methodMsg, bool finished)
|
{
|
string strCommand = string.Empty;
|
string strJson = "";
|
if (finished)
|
{
|
strJson = "{" + "message_id:\"" + Guid.NewGuid().ToString() +
|
"\",message_type:" + methodMsg.methodmsg_type +
|
",method:\"" + methodMsg.methodmsg_methodname + "\"" +
|
",equipment_id:\"" + methodMsg.methodmsg_machine_id + "\"" +
|
",workflow_id:\"\"" +
|
",experiment_id:\"" + methodMsg.methodmsg_experiment_id +
|
",dealwithtype:" + methodMsg.slovetype.ToString() +
|
",data:\"\"" +
|
",process_info:{}" +
|
",estimate_time:5" +
|
",timeout:60" +
|
",description:\"NO DESC\"" +
|
",timestamp:\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}";
|
}
|
else
|
{
|
strJson = "{" + "message_id:\"" + Guid.NewGuid().ToString() +
|
"\",message_type:" + methodMsg.methodmsg_type +
|
",method:\"" + methodMsg.methodmsg_methodname + "\"" +
|
",equipment_id:\"" + methodMsg.methodmsg_machine_id + "\"" +
|
",workflow_id:\"\"" +
|
",experiment_id:\"" + methodMsg.methodmsg_experiment_id +
|
"\",error:" +
|
"{" +
|
"error_code:\"" + methodMsg.error_code + "\"" +
|
",error_text:\"" + methodMsg.error_text + "\"" +
|
",troubleshoot:" + methodMsg.troubleshoot.ToString() + "" +
|
",dealwithtype:" + methodMsg.slovetype.ToString() +
|
"}" +
|
",data:\"\"" +
|
",process_info:{}" +
|
",estimate_time:5" +
|
",timeout:60" +
|
",description:\"NO DESC\"" +
|
",timestamp:\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}";
|
}
|
|
strCommand = strJson;
|
return strCommand;
|
}
|
|
/// <summary>
|
/// 断开连接
|
/// </summary>
|
public void CloseConnect()
|
{
|
try
|
{
|
if (m_socket != null)
|
{
|
// 关闭Socket实例
|
m_socket.Shutdown(SocketShutdown.Both);
|
m_socket.Close();
|
m_socket.Dispose();
|
m_socket = null;
|
}
|
}
|
catch (Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("[HxSocketClient][CloseConnect]:ERROR:", ex);
|
}
|
}
|
|
/// <summary>
|
/// 收到的消息添加到list中
|
/// </summary>
|
/// <param name="strRecvMessage"></param>
|
private void AddMessageToList(string strRecvMessage)
|
{
|
if (strRecvMessage.Length > 0)
|
{
|
// 防止两条命令合并为一条来接收
|
string[] asCommand = strRecvMessage.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
if (asCommand.Length >= 2)
|
{
|
lock (m_objListLock)
|
{
|
for (int i = 0; i < asCommand.Length; i++)
|
{
|
if (asCommand[i].Contains("COMMAND"))
|
{
|
if (asCommand[i].Contains("ID0")) //HeartBeat
|
{
|
//m_strDevicesConntectedStatus = asCommand[i].Substring(asCommand[i].IndexOf("COMMAND") + 7);
|
continue;
|
}
|
m_listRecvMessage.Add(asCommand[i] + "\r\n");
|
LoggerSocketHelper.InfoLog(string.Format("从{0}接收数据成功:{1}{2}", m_socket.RemoteEndPoint.ToString(), Environment.NewLine, asCommand[i]));
|
}
|
}
|
}
|
}
|
else
|
{
|
//过滤心跳
|
string ackSrc = asCommand[0];
|
string ack = ackSrc.Replace("#!HxSEP!#", "");
|
JObject job = JObject.Parse(ack);
|
int iType = Convert.ToInt32(job["message_type"].ToString());
|
|
if (iType == 0)
|
{
|
//LoggerSocketHelper.InfoLog(string.Format("从{0}接收心跳成功:{1}{2}", m_socket.RemoteEndPoint.ToString(), Environment.NewLine, asCommand[0]));
|
}
|
else if (iType == 4 || iType == 5)
|
{
|
string methodName = job["method"].ToString();
|
if (methodName != "ClawOpen")
|
{
|
m_listRecvMessage.Add(asCommand[0] + "\r\n");
|
m_countOfOnce++;
|
//LoggerSocketHelper.InfoLog(string.Format("从{0}接收数据成功:{1}{2}", m_socket.RemoteEndPoint.ToString(), Environment.NewLine, asCommand[0]));
|
}
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// 接收消息线程
|
/// </summary>
|
private void RecvThreadMethod()
|
{
|
try
|
{
|
byte[] data = new byte[1024];
|
|
while (true)
|
{
|
/* * 0表示从数组的哪个索引开始读取数据 * 1024 表示最大的读取数 * */
|
try
|
{
|
// 接收服务器响应数据
|
byte[] buffer = new byte[81920];
|
int bytesRec = 0;
|
if (m_socket == null)
|
{
|
LoggerSocketHelper.DebugLog("[HxSocketClient][RecvThreadMethod]:Release:");
|
break;
|
}
|
|
if (m_socket.Connected)
|
{
|
bytesRec = m_socket.Receive(buffer);
|
}
|
if (bytesRec == 0)
|
{
|
// 服务断了
|
return;
|
}
|
|
string strRecvMessage = Encoding.ASCII.GetString(buffer, 0, bytesRec);
|
AddMessageToList(strRecvMessage);
|
}
|
catch (System.Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("[HxSocketClient][RecvThreadMethod]:ERROR:", ex);
|
}
|
}
|
}
|
catch (System.Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("[HxSocketClient][RecvThreadMethod]:ERROR:", ex);
|
}
|
}
|
|
/// <summary>
|
/// 线程开始,启动函数
|
/// </summary>
|
public void StartRecvThread()
|
{
|
try
|
{
|
recvThread = new Thread(new ThreadStart(RecvThreadMethod));
|
recvThread.Start();
|
LoggerSocketHelper.InfoLog(string.Format("[HxSocketClient][StartRecvThread]:打开RecvThread成功!ip:{0},port:{1}", m_ip, m_port));
|
}
|
catch (Exception ex)
|
{
|
LoggerSocketHelper.ErrorLog("ERROR:", ex);
|
}
|
}
|
|
/// <summary>
|
/// 关闭接受数据线程
|
/// </summary>
|
private void CloceRecvThread()
|
{
|
try
|
{
|
if (recvThread != null)
|
{
|
recvThread.Abort();
|
}
|
}
|
catch (Exception ex)
|
{
|
}
|
}
|
|
/// <summary>
|
/// 获取通讯连接状态
|
/// </summary>
|
/// <returns></returns>
|
public bool IsConnect()
|
{
|
try
|
{
|
if (m_socket == null)
|
{
|
return false;
|
}
|
else
|
{
|
return !((m_socket.Poll(1000, SelectMode.SelectRead) && (m_socket.Available == 0)) ||
|
!m_socket.Connected);
|
}
|
}
|
catch (Exception ex)
|
{
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// 检查数据
|
/// </summary>
|
/// <param name="strResult"></param>
|
/// <returns></returns>
|
public string CheckData(List<string> listRetData)
|
{
|
string rtnData = string.Empty;
|
if (listRetData.Count == 2)
|
{
|
// 检查Data是否报错
|
string strFinish = listRetData[1];
|
string finishData = strFinish.Replace("#!HxSEP!#", "");
|
HxResponseBase rtData = JsonConvert.DeserializeObject<HxResponseBase>(finishData);
|
|
if (rtData.method_status == 3) // Failed
|
{
|
LoggerSocketHelper.DebugLog(string.Format("[CheckData]: method_status == 3, Response: {0}", listRetData[1]));
|
}
|
else if (rtData.message_type == 5 && rtData.method_status == 2) // Finish ComPleted
|
{
|
return finishData;
|
}
|
}
|
|
return rtnData;
|
}
|
}
|
}
|