TCPPortConnectionBase.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. using Aitex.Core.Util;
  2. using MECF.Framework.Common.Communications;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using HandlerBase = athosRT.tool.Comm.HandlerBase;
  11. //using TCPPortConnectionBase = athosRT.tool.Comm.TCPPortConnectionBase;
  12. namespace athosRT.tool.Comm
  13. {
  14. public abstract class TCPPortConnectionBase : IConnection
  15. {
  16. private AsynSocketClient _socket;
  17. protected HandlerBase _activeHandler;
  18. public HandlerBase HandlerInError;
  19. protected object _lockerActiveHandler = new object();
  20. private string _address;
  21. private bool _isAsciiMode;
  22. public int retryTime = 0;
  23. private PeriodicJob _thread;
  24. private object _locker = new object();
  25. private LinkedList<string> _lstAsciiMsgs = new LinkedList<string>();
  26. private LinkedList<byte[]> _lstBinsMsgs = new LinkedList<byte[]>();
  27. private string _newLine;
  28. public string Address => _address;
  29. public bool IsConnected => _socket.IsConnected;
  30. public bool IsBusy => _activeHandler != null;
  31. public bool IsCommunicationError { get; private set; }
  32. public string LastCommunicationError { get; private set; }
  33. public bool Connect()
  34. {
  35. _socket.Connect();
  36. int num = 0;
  37. while (!IsConnected && num < 25)
  38. {
  39. Thread.Sleep(200);//原本就有
  40. num++;
  41. }
  42. if (IsConnected)
  43. {
  44. return true;
  45. }
  46. Disconnect();
  47. return false;
  48. }
  49. public bool Disconnect()
  50. {
  51. _socket.Dispose();
  52. return true;
  53. }
  54. public TCPPortConnectionBase(string address, string newline = "\r", bool isAsciiMode = true)
  55. {
  56. _address = address;
  57. _newLine = newline;
  58. _isAsciiMode = isAsciiMode;
  59. _socket = new AsynSocketClient(address, isAsciiMode, newline);
  60. _socket.OnDataChanged += _port_OnAsciiDataReceived;
  61. _socket.OnBinaryDataChanged += _port_OnBinaryDataChanged;
  62. _socket.OnErrorHappened += _port_OnErrorHappened;
  63. _thread = new PeriodicJob(1, OnTimer, address + ".MonitorHandler", isStartNow: true);
  64. }
  65. private bool OnTimer()
  66. {
  67. lock (_locker)
  68. {
  69. if (_isAsciiMode)
  70. {
  71. while (_lstAsciiMsgs.Count > 0)
  72. {
  73. string value = _lstAsciiMsgs.First.Value;
  74. if (!string.IsNullOrEmpty(value))
  75. {
  76. if (_socket.NeedLog)
  77. {
  78. //LOG.Write("Start handler message:" + value, 2, "D:\\sorter\\trunk\\Framework\\Common\\Communications\\ConnectionBase.cs", "OnTimer", 412);
  79. }
  80. _port_HandleAsciiData(value);
  81. }
  82. _lstAsciiMsgs.RemoveFirst();
  83. }
  84. }
  85. else
  86. {
  87. while (_lstBinsMsgs.Count > 0)
  88. {
  89. byte[] value2 = _lstBinsMsgs.First.Value;
  90. _port_HandleBinarayData(value2);
  91. _lstBinsMsgs.RemoveFirst();
  92. }
  93. }
  94. }
  95. return true;
  96. }
  97. private void _port_OnErrorHappened(TCPErrorEventArgs obj)
  98. {
  99. //LOG.Error(obj.Reason, 2, "D:\\sorter\\trunk\\Framework\\Common\\Communications\\ConnectionBase.cs", "_port_OnErrorHappened", 439);
  100. }
  101. public virtual bool SendMessage(string message)
  102. {
  103. if (_socket != null && _socket.IsConnected)
  104. {
  105. return _socket.Write(message);
  106. }
  107. //LOG.Error("No connection writing message " + message, 2, "D:\\sorter\\trunk\\Framework\\Common\\Communications\\ConnectionBase.cs", "SendMessage", 447);
  108. return false;
  109. }
  110. public virtual bool SendMessage(byte[] message)
  111. {
  112. if (_socket != null && _socket.IsConnected)
  113. {
  114. return _socket.Write(message);
  115. }
  116. //LOG.Error("No connection writing message " + string.Join(" ", Array.ConvertAll(message, (byte x) => x.ToString("X2"))), 2, "D:\\sorter\\trunk\\Framework\\Common\\Communications\\ConnectionBase.cs", "SendMessage", 456);
  117. return false;
  118. }
  119. public void ForceClear()
  120. {
  121. lock (_lockerActiveHandler)
  122. {
  123. _activeHandler = null;
  124. IsCommunicationError = false;
  125. }
  126. }
  127. public void Execute(HandlerBase handler)
  128. {
  129. if (_activeHandler != null || handler == null || !_socket.IsConnected)
  130. {
  131. return;
  132. }
  133. lock (_lockerActiveHandler)
  134. {
  135. if (handler != null)
  136. {
  137. retryTime = 0;
  138. _activeHandler = handler;
  139. _activeHandler.SetState(EnumHandlerState.Sent);
  140. }
  141. }
  142. bool flag = _isAsciiMode ? SendMessage(handler.SendText) : SendMessage(handler.SendBinary);
  143. if (!flag)
  144. {
  145. //while (_lstAsciiMsgs.Count > 0)
  146. //{
  147. // string value = _lstAsciiMsgs.First!.Value;
  148. // if (!string.IsNullOrEmpty(value))
  149. // {
  150. // if (_socket.NeedLog)
  151. // {
  152. // //LOG.Write("Start handler message:" + value, 2, "D:\\sorter\\trunk\\Framework\\Common\\Communications\\ConnectionBase.cs", "OnTimer", 412);
  153. // }
  154. // _port_HandleAsciiData(value);
  155. // }
  156. // _lstAsciiMsgs.RemoveFirst();
  157. //}
  158. lock (_lockerActiveHandler)
  159. {
  160. //_activeHandler = null;
  161. }
  162. }
  163. }
  164. protected virtual MessageBase ParseResponse(string rawMessage)
  165. {
  166. return null;
  167. }
  168. protected virtual MessageBase ParseResponse(byte[] rawMessage)
  169. {
  170. return null;
  171. }
  172. protected virtual void OnEventArrived(MessageBase msg)
  173. {
  174. }
  175. protected virtual void ActiveHandlerProceedMessage(MessageBase msg)
  176. {
  177. //Trace.WriteLine("2222");
  178. //lock (_lockerActiveHandler)
  179. //{
  180. // //if (_activeHandler != null && (msg.IsFormatError || (_activeHandler.HandleMessage(msg, out var transactionComplete) && transactionComplete)))
  181. // if (_activeHandler != null)
  182. // {
  183. // bool flag = _activeHandler.HandleMessage(msg, out var transactionComplete);
  184. // Trace.WriteLine("333");
  185. // if (flag)
  186. // {
  187. // if (transactionComplete)
  188. // {
  189. // _activeHandler = null;
  190. // }
  191. // }
  192. // }
  193. //}
  194. }
  195. public void EnableLog(bool enable)
  196. {
  197. _socket.NeedLog = enable;
  198. }
  199. private void ProceedTransactionMessage(MessageBase msg)
  200. {
  201. if (msg?.IsFormatError ?? true)
  202. {
  203. SetCommunicationError(isError: true, "received invalid response message.");
  204. return;
  205. }
  206. if (msg.IsEvent)
  207. {
  208. OnEventArrived(msg);
  209. }
  210. //Trace.WriteLine("ProceedTransactionMessage");
  211. ActiveHandlerProceedMessage(msg);
  212. //Trace.WriteLine("ProceedTransactionMessage over");
  213. }
  214. private void _port_OnBinaryDataChanged(byte[] binaryData)
  215. {
  216. lock (_locker)
  217. {
  218. _lstBinsMsgs.AddLast(binaryData);
  219. }
  220. }
  221. private void _port_HandleBinarayData(byte[] binaryData)
  222. {
  223. MessageBase msg = ParseResponse(binaryData);
  224. ProceedTransactionMessage(msg);
  225. }
  226. private void _port_OnAsciiDataReceived(string oneLineMessage)
  227. {
  228. lock (_locker)
  229. {
  230. if (string.IsNullOrEmpty(_newLine))
  231. {
  232. _lstAsciiMsgs.AddLast(oneLineMessage);
  233. return;
  234. }
  235. string[] array = oneLineMessage.Split(_newLine.ToCharArray());
  236. foreach (string text in array)
  237. {
  238. if (!string.IsNullOrEmpty(text))
  239. {
  240. _lstAsciiMsgs.AddLast(text + _newLine);
  241. }
  242. }
  243. }
  244. }
  245. private void _port_HandleAsciiData(string oneLineMessage)
  246. {
  247. MessageBase msg = ParseResponse(oneLineMessage);
  248. //Trace.WriteLine("_port_HandleAsciiData1");
  249. ProceedTransactionMessage(msg);
  250. //Trace.WriteLine("_port_HandleAsciiData2");
  251. }
  252. public HandlerBase MonitorTimeout()
  253. {
  254. HandlerBase result = null;
  255. lock (_lockerActiveHandler)
  256. {
  257. if (_activeHandler != null && _activeHandler.CheckTimeout())
  258. {
  259. EV.PostWarningLog("System", Address + " receive " + _activeHandler.Name + " timeout");
  260. result = _activeHandler;
  261. HandlerInError = _activeHandler;
  262. _activeHandler = null;
  263. SetCommunicationError(isError: true, "receive response timeout");
  264. }
  265. }
  266. return result;
  267. }
  268. public void Retry()
  269. {
  270. //线程不安全且未被引用 暂时禁止使用
  271. //if (_activeHandler != null && _socket.IsConnected)
  272. //{
  273. // _activeHandler.SetState(EnumHandlerState.Sent);
  274. // if (!(_isAsciiMode ? SendMessage(_activeHandler.SendText) : SendMessage(_activeHandler.SendBinary)))
  275. // {
  276. // _activeHandler = null;
  277. // }
  278. //}
  279. }
  280. public void SetCommunicationError(bool isError, string reason)
  281. {
  282. IsCommunicationError = isError;
  283. LastCommunicationError = reason;
  284. }
  285. }
  286. }