CSNetComm.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.Threading;
  7. using System.Net.Sockets;
  8. using BlackBoxFile;
  9. namespace Dispatch
  10. {
  11. /// <summary>
  12. /// 网络通信类
  13. /// </summary>
  14. public class CSNetComm
  15. {
  16. private static Thread gs_netThread; // 网络线程
  17. private static bool gs_startFlag; // 启动标志位
  18. private static bool gs_pauseFlag; // 暂停标志位
  19. private static IPAddress gs_ipAddr; // IP地址
  20. private static int gs_listenPort; // 监听端口
  21. private static CSNetServer gs_server;
  22. private static List<CSNetConThread> gs_nctList;
  23. private static ManualResetEvent gs_resumeEvent;
  24. private static List<byte> gs_netBuffer;
  25. private static object netLock = new object();
  26. private static Thread threadNet;
  27. /// <summary>
  28. ///
  29. /// </summary>
  30. /// <param name="sender"></param>
  31. /// <param name="e"></param>
  32. public delegate void MatchedParityHandler(object sender, DataEventArgs e);
  33. /// <summary>
  34. ///
  35. /// </summary>
  36. public static event MatchedParityHandler MatchedParity;
  37. private static void OnMatchedParity(object sender, DataEventArgs e)
  38. {
  39. if (MatchedParity != null)
  40. {
  41. MatchedParity(sender, e);
  42. }
  43. }
  44. /// <summary>
  45. ///
  46. /// </summary>
  47. /// <param name="o"></param>
  48. public static void OnMatchParity(object o)
  49. {
  50. MyNetData data = o as MyNetData;
  51. Console.ForegroundColor = ConsoleColor.Yellow;
  52. //Console.WriteLine("所在线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString() + "类型:" + data.e.type + " " + CHex2String.Byte2HexString(data.e.data, data.e.data.Length));
  53. Console.ResetColor();
  54. OnMatchedParity(data.sender, data.e);
  55. Thread.Sleep(500);//加延时是为了避免解析后有过长的操作占用系统资源
  56. }
  57. private class MyNetData
  58. {
  59. /// <summary>
  60. /// 对象
  61. /// </summary>
  62. public object sender;
  63. /// <summary>
  64. /// 事务
  65. /// </summary>
  66. public DataEventArgs e;
  67. }
  68. /// <summary>
  69. ///
  70. /// </summary>
  71. public CSNetComm()
  72. {
  73. gs_startFlag = false;
  74. gs_pauseFlag = false;
  75. gs_ipAddr = IPAddress.Parse("127.0.0.1");
  76. gs_listenPort = 8899;
  77. gs_nctList = new List<CSNetConThread>();
  78. gs_resumeEvent = new ManualResetEvent(false);
  79. gs_netBuffer = new List<byte>();
  80. threadNet = new Thread(ThreadHandler);
  81. threadNet.Start();
  82. }
  83. /// <summary>
  84. /// 初始化
  85. /// </summary>
  86. /// <param name="ipAddr"></param>
  87. /// <param name="listenPort"></param>
  88. public static void Init(IPAddress ipAddr, int listenPort)
  89. {
  90. gs_ipAddr = ipAddr;
  91. gs_listenPort = listenPort;
  92. gs_server = new CSNetServer(gs_ipAddr, gs_listenPort);
  93. }
  94. /// <summary>
  95. /// 发送字节数据
  96. /// </summary>
  97. /// <param name="n">连接线程ID</param>
  98. /// <param name="buffer">数据缓冲区</param>
  99. /// <param name="length">数据长度</param>
  100. public static void SendBytes(int n, byte[] buffer, int length)
  101. {
  102. //foreach (CSNetConThread nct in gs_nctList)
  103. for (int i = 0; i < gs_nctList.Count; i++)
  104. {
  105. CSNetConThread nct = gs_nctList[i];
  106. nct.SendBytes(buffer, length);
  107. }
  108. }
  109. /// <summary>
  110. /// 获取线程挂起状态
  111. /// </summary>
  112. /// <returns></returns>
  113. public static bool GetPauseStatus()
  114. {
  115. return gs_pauseFlag;
  116. }
  117. /// <summary>
  118. /// 获取服务器开启状态
  119. /// </summary>
  120. /// <returns></returns>
  121. public static bool GetStartStatus()
  122. {
  123. return gs_startFlag;
  124. }
  125. /// <summary>
  126. /// 线程暂停
  127. /// </summary>
  128. public static void Pause()
  129. {
  130. gs_resumeEvent.Reset();
  131. gs_pauseFlag = true;
  132. }
  133. /// <summary>
  134. /// 线程恢复
  135. /// </summary>
  136. public static void Resume()
  137. {
  138. gs_resumeEvent.Set();
  139. gs_pauseFlag = true;
  140. }
  141. /// <summary>
  142. /// 启动
  143. /// </summary>
  144. public static void Start(string ipAddr, int listenPort)
  145. {
  146. gs_ipAddr = IPAddress.Parse(ipAddr);
  147. gs_listenPort = listenPort;
  148. // 开启网络监听线程
  149. gs_netThread = new Thread(new ThreadStart(ThreadProc));
  150. gs_netThread.Start();
  151. }
  152. /// <summary>
  153. /// 停止
  154. /// </summary>
  155. public static void Stop()
  156. {
  157. if (!gs_startFlag)
  158. {
  159. return;
  160. }
  161. gs_startFlag = false;
  162. while (CSNetConThread.GetConnectedNum() != 0)
  163. {
  164. Thread.Sleep(10);
  165. }
  166. gs_server.Stop();
  167. gs_netThread.Abort();
  168. }
  169. /// <summary>
  170. /// 添加网络连接线程实例
  171. /// </summary>
  172. /// <param name="nct">网络连接线程实例</param>
  173. public static void AddNetConThread(CSNetConThread nct)
  174. {
  175. gs_nctList.Add(nct);
  176. }
  177. /// <summary>
  178. /// 删除网络连接线程实例
  179. /// </summary>
  180. /// <param name="nct">网络连接线程实例</param>
  181. public static void RemoveNetConThread(CSNetConThread nct)
  182. {
  183. gs_nctList.Remove(nct);
  184. }
  185. /// <summary>
  186. ///
  187. /// </summary>
  188. /// <param name="n"></param>
  189. public void RemoveNetThread(int n)
  190. {
  191. bool flag = false;
  192. CSNetConThread delnct = new CSNetConThread();
  193. foreach (CSNetConThread nct in gs_nctList)
  194. {
  195. if (n == nct.GetID())
  196. {
  197. flag = true;
  198. delnct = nct;
  199. break;
  200. }
  201. }
  202. if (flag)
  203. {
  204. CSNetConThread.gs_connectedNum--;
  205. delnct.CloseClient();
  206. RemoveNetConThread(delnct);
  207. }
  208. }
  209. /// <summary>
  210. /// 线程过程
  211. /// </summary>
  212. private static void ThreadProc()
  213. {
  214. gs_server = new CSNetServer(gs_ipAddr, gs_listenPort);
  215. gs_startFlag = gs_server.Start();
  216. if (!gs_startFlag)
  217. {
  218. return;
  219. }
  220. while (true)
  221. {
  222. // 如果线程已被挂起
  223. if (gs_pauseFlag)
  224. {
  225. //gs_resumeEvent.WaitOne();
  226. }
  227. while (!gs_server.Pending())
  228. {
  229. Thread.Sleep(1000); // 延时1秒
  230. }
  231. /************************************************************************/
  232. /* 利用线程池技术开启新连接 */
  233. /************************************************************************/
  234. CSNetConThread newConThread = new CSNetConThread();
  235. newConThread.SetListener(gs_server.GetListener());
  236. //ThreadPool.QueueUserWorkItem(new WaitCallback(newConThread.ThreadProc));
  237. Thread thread = new Thread(new ThreadStart(newConThread.ThreadProc));
  238. thread.Start();
  239. Pause();
  240. }
  241. }
  242. /// <summary>
  243. /// 批量追加网络数据缓存
  244. /// </summary>
  245. /// <param name="buffer">数据缓存</param>
  246. /// <param name="length">数据长度</param>
  247. public static void AddNetBufferRange(byte[] buffer, int length)
  248. {
  249. for (int i = 0; i < length; i++)
  250. {
  251. gs_netBuffer.Add(buffer[i]);
  252. }
  253. }
  254. private static byte[] DataHander(out int type)
  255. {
  256. type = -1;
  257. int framelength = 14; // 帧长度
  258. byte frameHead = 0x10; // 帧头
  259. byte frameTaig = 0x03;
  260. byte frameFunc1 = 0x41;
  261. byte frameFunc2 = 0x42;
  262. byte frameFunc3 = 0x53;
  263. byte frameFunc4 = 0x54;
  264. if (gs_netBuffer.Count >= framelength)
  265. {
  266. #region MyRegion
  267. if ((gs_netBuffer[0] == frameHead) && (gs_netBuffer[2] == frameFunc1 || gs_netBuffer[2] == frameFunc2
  268. || gs_netBuffer[2] == frameFunc3 || gs_netBuffer[2] == frameFunc4) && (gs_netBuffer[13] == frameTaig))
  269. {
  270. byte checkSum = 0x00;
  271. for (int i = 0; i < 12; i++)
  272. {
  273. checkSum ^= gs_netBuffer[i];
  274. }
  275. if (checkSum == gs_netBuffer[12])
  276. {
  277. byte[] data = new byte[14];
  278. for (int i = 0; i < 14; i++)
  279. {
  280. data[i] = gs_netBuffer[i];
  281. }
  282. lock (netLock)
  283. {
  284. gs_netBuffer.RemoveRange(0, 14);
  285. }
  286. type = 2;
  287. return data;
  288. }
  289. else
  290. {
  291. ArrangeBuffer(gs_netBuffer, frameHead);
  292. }
  293. }
  294. else if ((gs_netBuffer[0] == frameHead) && (gs_netBuffer.Count >= 10) && gs_netBuffer[1] == 0x62)//轮询的解析
  295. {
  296. byte checkSum = 0x00;
  297. for (int i = 0; i < 8; i++)
  298. {
  299. checkSum ^= gs_netBuffer[i];
  300. }
  301. if (checkSum == gs_netBuffer[8] && frameTaig == gs_netBuffer[9])
  302. {
  303. byte[] data = new byte[10];
  304. for (int i = 0; i < 10; i++)
  305. {
  306. data[i] = gs_netBuffer[i];
  307. }
  308. lock (netLock)
  309. {
  310. gs_netBuffer.RemoveRange(0, 10);
  311. }
  312. type = 2;
  313. return data;
  314. }
  315. else
  316. {
  317. ArrangeBuffer(gs_netBuffer, frameHead);
  318. }
  319. }
  320. else
  321. {
  322. ArrangeBuffer(gs_netBuffer, frameHead);
  323. }
  324. #endregion
  325. }
  326. return new byte[1] { 0 };
  327. }
  328. static AutoResetEvent done = new AutoResetEvent(true);//在处理数据的时候不允许被打断(只有在线程正常挂起时有效)
  329. /// <summary>
  330. ///
  331. /// </summary>
  332. public void ThreadHandler()
  333. {
  334. while (true)
  335. {
  336. //Console.WriteLine("分析线程运行中...");
  337. if (gs_netBuffer.Count > 0)
  338. {
  339. done.Reset();
  340. byte[] buffer;
  341. int type;
  342. buffer = DataHander(out type);
  343. DataEventArgs e = new DataEventArgs();
  344. e.type = type;
  345. e.data = buffer;
  346. if (type != -1)
  347. {
  348. MyNetData data = new MyNetData();
  349. data.sender = this;
  350. data.e = e;
  351. Thread t = new Thread(OnMatchParity);
  352. t.Start(data);
  353. }
  354. }
  355. Thread.Sleep(20);
  356. done.Set();
  357. }
  358. }
  359. /// <summary>
  360. /// 整理数据缓存表
  361. /// </summary>
  362. /// <param name="bufferList">数据缓存表</param>
  363. /// <param name="targetByte">目标字节</param>
  364. private static void ArrangeBuffer(List<byte> bufferList, byte targetByte)
  365. {
  366. int delBytes = 1;
  367. for (int i = 1; i < bufferList.Count; i++)
  368. {
  369. if (bufferList[i] == targetByte)
  370. {
  371. break;
  372. }
  373. else
  374. {
  375. delBytes++;
  376. }
  377. }
  378. try
  379. {
  380. lock (netLock)
  381. {
  382. bufferList.RemoveRange(0, delBytes);
  383. }
  384. }
  385. catch (Exception ex)
  386. {
  387. throw ex;
  388. }
  389. }
  390. /// <summary>
  391. /// 网路连接线程类
  392. /// </summary>
  393. public class CSNetConThread
  394. {
  395. /// <summary>
  396. /// 已建立连接数
  397. /// </summary>
  398. public static int gs_connectedNum = 0; //
  399. private const int gc_bufferSize = 1024; // 缓冲区的大小
  400. private static List<byte> gs_netBuffer; // 网络数据缓存
  401. /// <summary>
  402. /// TCP联接
  403. /// </summary>
  404. public TcpClient tcpclient;
  405. private TcpListener listener;
  406. private int id;
  407. private int rxBytes;
  408. private int txBytes;
  409. private byte[] rxBuffer;
  410. private byte[] txBuffer;
  411. //private bool readFlag;
  412. private bool writeFlag;
  413. /// <summary>
  414. /// 默认构造
  415. /// </summary>
  416. public CSNetConThread()
  417. {
  418. id = 0;
  419. rxBytes = 0;
  420. txBytes = 0;
  421. //readFlag = false;
  422. writeFlag = false;
  423. rxBuffer = new byte[gc_bufferSize];
  424. txBuffer = new byte[gc_bufferSize];
  425. gs_netBuffer = new List<byte>();
  426. tcpclient = new TcpClient();
  427. }
  428. /// <summary>
  429. /// 获取连接线程ID
  430. /// </summary>
  431. /// <returns>连接线程ID</returns>
  432. public int GetID()
  433. {
  434. return this.id;
  435. }
  436. private int GenerateID()
  437. {
  438. int id = 0;
  439. id = gs_connectedNum;
  440. return id;
  441. }
  442. /// <summary>
  443. /// 关闭所有联接
  444. /// </summary>
  445. public void CloseClient()
  446. {
  447. IPEndPoint iep = (IPEndPoint)tcpclient.Client.RemoteEndPoint;
  448. tcpclient.Close();
  449. }
  450. /// <summary>
  451. /// 获取联接数量
  452. /// </summary>
  453. /// <returns></returns>
  454. public static int GetConnectedNum()
  455. {
  456. return gs_connectedNum;
  457. }
  458. /// <summary>
  459. /// 设置监听器
  460. /// </summary>
  461. /// <param name="tl">TCP监听器</param>
  462. public void SetListener(TcpListener tl)
  463. {
  464. this.listener = tl;
  465. }
  466. /// <summary>
  467. /// 发送字节数组
  468. /// </summary>
  469. /// <param name="buffer"></param>
  470. /// <param name="length"></param>
  471. public void SendBytes(byte[] buffer, int length)
  472. {
  473. while (writeFlag)
  474. {
  475. Thread.Sleep(10);
  476. }
  477. txBuffer = buffer;
  478. txBytes = length;
  479. writeFlag = true;
  480. }
  481. /// <summary>
  482. /// 线程执行过程
  483. /// </summary>
  484. public void ThreadProc()//object state
  485. {
  486. bool acceptFlag = true;
  487. TcpClient client = new TcpClient();
  488. try
  489. {
  490. client = listener.AcceptTcpClient();
  491. }
  492. catch (SocketException ex)
  493. {
  494. string str = "";
  495. string strDateInfo = "出现的异常:" + DateTime.Now.ToString() + "\r\n";
  496. if (ex != null)
  497. {
  498. str = string.Format(strDateInfo + "异常类型:{0}\r\n异常消息:{1}\r\n异常信息:{2}\r\n",
  499. ex.GetType().Name, ex.Message, ex.StackTrace);
  500. }
  501. else
  502. {
  503. str = string.Format("应用程序线程错误:{0}", ex);
  504. }
  505. Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, str);
  506. //Program.writeLog(str);
  507. // 此处需要发送异常消息
  508. acceptFlag = false;
  509. }
  510. tcpclient = client;
  511. IPEndPoint iep1 = (IPEndPoint)tcpclient.Client.RemoteEndPoint;
  512. //////////////////////////////////////////////////
  513. gs_connectedNum++;
  514. ////////////////////////////////////////////////////
  515. //this.id = GenerateID();
  516. CSNetComm.AddNetConThread(this);
  517. // 等待网络通信监听线程挂起,然后恢复该线程运行
  518. //while (!CSNetComm.GetPauseStatus())
  519. //{}
  520. CSNetComm.Resume();
  521. #region 连接成功
  522. if (acceptFlag)
  523. {
  524. NetworkStream ns = client.GetStream();
  525. // 发送已连接事件
  526. IPEndPoint iep = (IPEndPoint)client.Client.RemoteEndPoint;
  527. string ipStr = iep.Address.ToString();
  528. string portStr = "[" + iep.Port.ToString() + "]";
  529. string msgText = "Client" + this.id.ToString() + "\t\t" + ipStr + "\t" + portStr;
  530. //SendMessage(MessgeType.EVENT_CLIENT_CONNECTED, msgText, 0, 0);
  531. //发送欢迎语
  532. //string welcomeStr = "Welcome to CASUN CMS Server!";
  533. //rxBuffer = Encoding.ASCII.GetBytes(welcomeStr);
  534. //ns.Write(rxBuffer, 0, rxBuffer.Length);
  535. /************************************************************************/
  536. /* 数据发送操作 */
  537. /************************************************************************/
  538. #region
  539. while (true)
  540. {
  541. // 查询通信监听服务器是否打开
  542. if (!CSNetComm.GetStartStatus())
  543. {
  544. break;
  545. }
  546. if (client.Connected == false)
  547. {
  548. break;
  549. }
  550. // 检测当前套接字1ms是否为可读
  551. if (client.Client.Poll(1000, SelectMode.SelectRead))
  552. {
  553. try
  554. {
  555. rxBytes = ns.Read(rxBuffer, 0, rxBuffer.Length);
  556. }
  557. catch (System.Exception ex)
  558. {
  559. Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
  560. }
  561. if (rxBytes > 0)
  562. {
  563. this.id = rxBuffer[2];
  564. }
  565. //如果连接已关闭
  566. if (rxBytes == 0)
  567. {
  568. msgText = "Client" + this.id.ToString() + "\t\t" + ipStr + "\t" + portStr;
  569. //SendMessage(MessgeType.EVENT_CLIENT_DISCONNECTED, msgText, 0, 0);
  570. break;
  571. }
  572. else
  573. {
  574. string str = null;
  575. for (int i = 0; i < rxBytes; i++)
  576. str += Convert.ToString(rxBuffer[i], 16).ToString() + " ";
  577. //writeLog1(DateTime.Now.ToString() + str);
  578. CSNetComm.AddNetBufferRange(rxBuffer, rxBytes);
  579. //发送工作数据接收消息
  580. //SendMessage(MessgeType.EVENT_WORK_DATA_RECEIVED, "", recvNum, this.id);
  581. }
  582. }
  583. if (client.Connected == false)
  584. {
  585. break;
  586. }
  587. // 检测当前套接字1ms内是否为可写
  588. if (client.Client.Poll(1000, SelectMode.SelectWrite))
  589. {
  590. if (writeFlag)
  591. {
  592. try
  593. {
  594. ns.Write(txBuffer, 0, txBytes);
  595. }
  596. catch (Exception ex)
  597. {
  598. Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
  599. }
  600. writeFlag = false;
  601. Encoding e = Encoding.GetEncoding(936);
  602. msgText = e.GetString(txBuffer, 0, txBytes);
  603. //SendMessage(MessgeType.EVENT_DATA_SENDED, msgText, sendNum, this.id);
  604. }
  605. }
  606. }// end of while
  607. #endregion
  608. ns.Close();
  609. }// end of if ( acceptFlag )
  610. #endregion
  611. // 接入线程执行完毕需要的相关操作
  612. client.Close();
  613. gs_connectedNum--;
  614. CSNetComm.RemoveNetConThread(this);
  615. }
  616. }
  617. }
  618. /// <summary>
  619. /// 网络服务器类
  620. /// </summary>
  621. internal class CSNetServer
  622. {
  623. // 成员变量
  624. private TcpListener listener;
  625. // 成员函数
  626. /// <summary>
  627. /// 默认构造
  628. /// </summary>
  629. public CSNetServer()
  630. {
  631. string ipStr = "127.0.0.1";
  632. int port = 9808;
  633. this.listener = new TcpListener(IPAddress.Parse(ipStr), port);
  634. }
  635. /// <summary>
  636. /// 重载构造
  637. /// </summary>
  638. /// <param name="addr">地址</param>
  639. /// <param name="port">端口</param>
  640. public CSNetServer(IPAddress addr, int port)
  641. {
  642. this.listener = new TcpListener(addr, port);
  643. }
  644. public bool Pending()
  645. {
  646. try
  647. {
  648. return listener.Pending();
  649. }
  650. catch (System.Exception ex)
  651. {
  652. //需要向控制线程传递ex.Message
  653. Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
  654. return false;
  655. }
  656. }
  657. public bool Start()
  658. {
  659. try
  660. {
  661. listener.Start();
  662. }
  663. catch (System.Exception ex)
  664. {
  665. //需要向控制线程传递ex.Message
  666. Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
  667. return false;
  668. }
  669. return true;
  670. }
  671. public bool Stop()
  672. {
  673. try
  674. {
  675. listener.Stop();
  676. }
  677. catch (System.Exception ex)
  678. {
  679. //需要向控制线程传递ex.Message
  680. Dispatch.Dispatcher.gs_blackBoxFile.WriteFile(900, ex.Message);
  681. return false;
  682. }
  683. return true;
  684. }
  685. public TcpListener GetListener()
  686. {
  687. return (this.listener);
  688. }
  689. public void SetListener(IPAddress addr, int port)
  690. {
  691. //this.listener. ;
  692. }
  693. }
  694. }