No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Client.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //
  2. // Client.cs
  3. //
  4. // Author:
  5. // Di MERCURIO Sébastien <dimercur@insa-toulouse.fr>
  6. //
  7. // Copyright (c) 2018 INSA - DGEI
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU General Public License as published by
  11. // the Free Software Foundation, either version 3 of the License, or
  12. // (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. // GNU General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public License
  20. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. using System;
  22. using System.Net.Sockets;
  23. using System.Text;
  24. using System.Threading;
  25. namespace monitor
  26. {
  27. /// <summary>
  28. /// Static class for TCP client
  29. /// </summary>
  30. public static class Client
  31. {
  32. /// <summary>
  33. /// Default server name
  34. /// </summary>
  35. public const string defaultIP = "localhost";
  36. /// <summary>
  37. /// Default server port number
  38. /// </summary>
  39. public const int defaultPort = 5544;
  40. /// <summary>
  41. /// Tcp client object
  42. /// </summary>
  43. private static TcpClient client = null;
  44. /// <summary>
  45. /// Stream object used for communication
  46. /// </summary>
  47. private static NetworkStream stream = null;
  48. /// <summary>
  49. /// Size of internal buffer used when reading data from server
  50. /// </summary>
  51. private const int BufferMaxSize = 512;
  52. /// <summary>
  53. /// Internal buffer used when reading data from server
  54. /// </summary>
  55. private static byte[] buffer = new byte[BufferMaxSize];
  56. /// <summary>
  57. /// buffer containing received message from TCP server
  58. /// Used to concatenate internal buffers into one
  59. /// </summary>
  60. private static byte[] receiveBuffer;
  61. //private static int initialReceiveBufferIndex = 0;
  62. /// <summary>
  63. /// String containing received message from tcp server
  64. /// </summary>
  65. private static StringBuilder message = new StringBuilder();
  66. //private static int newLength = 1;
  67. //private static int packetCounter = 0;
  68. /// <summary>
  69. /// Callback to send received message to upper level
  70. /// </summary>
  71. public delegate void ReadEvent(string msg);
  72. public static ReadEvent readEvent = null;
  73. /// <summary>
  74. /// Thread used in reception
  75. /// </summary>
  76. private static Thread readThread;
  77. /// <summary>
  78. /// Open connection to server "host", on default port number.
  79. /// </summary>
  80. /// <returns>true if connection succeded, false otherwise</returns>
  81. /// <param name="host">Hostname to connect to</param>
  82. public static bool Open(string host)
  83. {
  84. return Client.Open(host, defaultPort);
  85. }
  86. /// <summary>
  87. /// Open connection to server "host", with port number "port"
  88. /// </summary>
  89. /// <returns>true if connection succeded, false otherwise</returns>
  90. /// <param name="host">Hostname to connect to</param>
  91. /// <param name="port">Port number for connection</param>
  92. public static bool Open(string host, int port)
  93. {
  94. bool status = true;
  95. try
  96. {
  97. client = new TcpClient(host, port);
  98. stream = client.GetStream();
  99. // Start reading tcp stream and call "ReadCallback" method when newLength data
  100. // will be received
  101. // initially, "newLength" is equal to 1, so first call to ReadCallback
  102. // will be done after reception of 1 byte.
  103. // received data are stored in buffer
  104. // Next reading will be done in ReadCallback method
  105. stream.BeginRead(buffer, 0, 1, new AsyncCallback(ReadCallback), message);
  106. // Start reading thread
  107. //message.Clear();
  108. //readThread = new Thread(new ThreadStart(ReadCallback));
  109. //readThread.Start();
  110. }
  111. catch (ArgumentNullException e)
  112. {
  113. Console.WriteLine("ArgumentNullException: " + e);
  114. status = false;
  115. }
  116. catch (SocketException e)
  117. {
  118. Console.WriteLine("SocketException: " + e.ToString());
  119. status = false;
  120. }
  121. catch (Exception e)
  122. {
  123. Console.WriteLine("Unknown Exception: " + e.ToString());
  124. status = false;
  125. }
  126. return status;
  127. }
  128. /// <summary>
  129. /// Close connection to server
  130. /// </summary>
  131. public static void Close()
  132. {
  133. if (stream != null) stream.Close();
  134. if (client != null) client.Close();
  135. }
  136. /// <summary>
  137. /// Callback call by stream.BeginRead after reception of newLength data
  138. /// </summary>
  139. //private static void ReadCallback()
  140. //{
  141. // char character;
  142. // int data;
  143. // byte[] buffer=new byte[4096];
  144. // int lengthRead;
  145. // while (client.Connected)
  146. // {
  147. // try
  148. // {
  149. // //data = stream.ReadByte();
  150. // lengthRead = stream.Read(buffer, 0, buffer.Length);
  151. // }
  152. // catch (ObjectDisposedException)
  153. // {
  154. // Console.WriteLine("Connection to server dropped (object disposed)!");
  155. // return;
  156. // }
  157. // catch (System.IO.IOException)
  158. // {
  159. // Console.WriteLine("Connection to server dropped (other error)");
  160. // return;
  161. // }
  162. // if (lengthRead > 0) // a data was read
  163. // {
  164. // //character = (char)data;
  165. // var str = System.Text.Encoding.Default.GetString(buffer);
  166. // int indexOf = str.IndexOf('\n');
  167. // //if (character != '\n')
  168. // if (indexOf == -1) // \n doesn't exists
  169. // {
  170. // message.Append(str);
  171. // //if (receiveBuffer == null) receiveBuffer = new byte[1];
  172. // //else Array.Resize<byte>(ref receiveBuffer, receiveBuffer.Length + 1); // resize currrent buffer
  173. // //receiveBuffer[receiveBuffer.Length - 1] = (byte)data;
  174. // }
  175. // else // end of string found
  176. // {
  177. // message.Append((str.Substring(0,indexOf)));
  178. // readEvent?.Invoke(message.ToString(), receiveBuffer);
  179. // message.Clear();
  180. // receiveBuffer = null;
  181. // }
  182. // }
  183. // }
  184. //}
  185. /// <summary>
  186. /// Callback call by stream.BeginRead after reception of newLength data
  187. /// </summary>
  188. /// <param name="ar">Not sure of what is it, but needed for terminate reading</param>
  189. //private static void ReadCallback(IAsyncResult ar)
  190. //{
  191. // if (client.Connected)
  192. // {
  193. // int bytesRead;
  194. // try
  195. // {
  196. // // Termintae read operation, and get number of byte stored in buffer
  197. // bytesRead = stream.EndRead(ar);
  198. // }
  199. // catch (ObjectDisposedException e)
  200. // {
  201. // Console.WriteLine("Connection to server dropped: " + e.ToString());
  202. // return;
  203. // }
  204. // newLength = 1;
  205. // // if number of byte read is not 0, concatenate string and buffer
  206. // if (bytesRead > 0)
  207. // {
  208. // packetCounter++;
  209. // if (packetCounter >= 3)
  210. // {
  211. // //Console.WriteLine("Supplementary packet " + packetCounter);
  212. // }
  213. // // Append new data to current string (expecting data are ascii)
  214. // message.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
  215. // // Similarly, append received bytes to current buffer
  216. // if (receiveBuffer == null) receiveBuffer = new byte[bytesRead];
  217. // else Array.Resize<byte>(ref receiveBuffer, initialReceiveBufferIndex + bytesRead); // resize currrent buffer
  218. // System.Buffer.BlockCopy(buffer, 0, receiveBuffer, initialReceiveBufferIndex, bytesRead); // and add received data
  219. // initialReceiveBufferIndex = receiveBuffer.Length; // move last index of current buffer
  220. // }
  221. // // if it remains received data, prepare for a new reading (get another buffer to append to current one)
  222. // if (client.Available > 0)
  223. // {
  224. // newLength = client.Available;
  225. // if (newLength > BufferMaxSize) newLength = BufferMaxSize;
  226. // else newLength = client.Available;
  227. // }
  228. // else
  229. // {
  230. // // no more data to read, buffer and string can be send to upper level
  231. // readEvent?.Invoke(message.ToString(), receiveBuffer);
  232. // message.Clear();
  233. // receiveBuffer = null;
  234. // initialReceiveBufferIndex = 0;
  235. // packetCounter = 0;
  236. // }
  237. // // Prepare for reading new data
  238. // if (newLength> BufferMaxSize) newLength = BufferMaxSize;
  239. // if (newLength <= 0) newLength = 1;
  240. // stream.BeginRead(buffer, 0, newLength, new AsyncCallback(ReadCallback), message);
  241. // }
  242. //}
  243. private static void ReadCallback(IAsyncResult ar)
  244. {
  245. int newLength = 1;
  246. if (client.Connected)
  247. {
  248. int bytesRead;
  249. try
  250. {
  251. // Terminate read operation, and get number of byte stored in buffer
  252. bytesRead = stream.EndRead(ar);
  253. }
  254. catch (ObjectDisposedException e)
  255. {
  256. Console.WriteLine("Connection to server dropped: " + e.ToString());
  257. return;
  258. }
  259. //newLength = 1;
  260. // if number of byte read is not 0, concatenate string and buffer
  261. if (bytesRead > 0)
  262. {
  263. // Append new data to current string (expecting data are ascii)
  264. message.Append(Encoding.ASCII.GetString(buffer, 0, bytesRead));
  265. }
  266. // if it remains received data, prepare for a new reading (get another buffer to append to current one)
  267. if (client.Available > 0)
  268. {
  269. newLength = client.Available;
  270. if (newLength > BufferMaxSize) newLength = BufferMaxSize;
  271. else newLength = client.Available;
  272. }
  273. else
  274. {
  275. // no more data to read, buffer and string can be send to upper level
  276. readEvent?.Invoke(message.ToString());
  277. message.Clear();
  278. }
  279. // Prepare for reading new data
  280. if (newLength> BufferMaxSize) newLength = BufferMaxSize;
  281. if (newLength <= 0) newLength = 1;
  282. stream.BeginRead(buffer, 0, newLength, new AsyncCallback(ReadCallback), message);
  283. }
  284. }
  285. /// <summary>
  286. /// Write a string to server
  287. /// </summary>
  288. /// <returns>Nothing</returns>
  289. /// <param name="mes">Message to send to server</param>
  290. public static void Write(string mes)
  291. {
  292. if (client.Connected)
  293. {
  294. byte[] writeBuffer = Encoding.UTF8.GetBytes(mes);
  295. stream.Write(writeBuffer, 0, mes.Length);
  296. }
  297. }
  298. }
  299. }