PageRenderTime 24ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Client/MessageClient.cs

#
C# | 310 lines | 149 code | 38 blank | 123 comment | 20 complexity | d363f49d42c729831a026737c1df0c24 MD5 | raw file
  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <copyright file="MessageClient.cs" company="Alexey Zakharov">
  3. // This file is part of SocketsLight Framework.
  4. //
  5. // SocketsLight Framework is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SocketsLight Framework is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with Foobar. If not, see http://www.gnu.org/license.
  17. // </copyright>
  18. // <summary>
  19. // Defines the MessageClient type.
  20. // </summary>
  21. // --------------------------------------------------------------------------------------------------------------------
  22. namespace Witcraft.SocketsLight.Client
  23. {
  24. using System;
  25. using System.Collections.Generic;
  26. using System.ComponentModel;
  27. using System.Linq;
  28. using System.Net;
  29. using System.Net.Sockets;
  30. using System.Windows;
  31. using Witcraft.SocketsLight.Server;
  32. /// <summary>
  33. /// Send and recives messages.
  34. /// </summary>
  35. public class MessageClient : IMessageClient
  36. {
  37. /// <summary>
  38. /// Used to aggregate message frames.
  39. /// </summary>
  40. private List<byte> messageBuffer = new List<byte>();
  41. /// <summary>
  42. /// Serialize and deserialize messages.
  43. /// </summary>
  44. private IMessageSerializer messageSerializer;
  45. /// <summary>
  46. /// Port which will be used for message transfer.
  47. /// </summary>
  48. private int port;
  49. /// <summary>
  50. /// Socket which will be used for message transfer.
  51. /// </summary>
  52. private Socket socket;
  53. /// <summary>
  54. /// Initializes a new instance of the <see cref="MessageClient"/> class.
  55. /// </summary>
  56. /// <param name="port">
  57. /// </param>
  58. /// <param name="messageSerializer">
  59. /// </param>
  60. public MessageClient(int port, IMessageSerializer messageSerializer)
  61. {
  62. this.port = port;
  63. this.messageSerializer = messageSerializer;
  64. this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  65. }
  66. /// <summary>
  67. /// Prevents a default instance of the <see cref="MessageClient"/> class from being created.
  68. /// </summary>
  69. private MessageClient()
  70. {
  71. }
  72. /// <summary>
  73. /// Occurs when client has connected to message server
  74. /// </summary>
  75. public event EventHandler<AsyncCompletedEventArgs> ConnectCompleted;
  76. /// <summary>
  77. /// Occure if connection with message server has been lost.
  78. /// </summary>
  79. public event EventHandler<EventArgs> ConnectionLost;
  80. /// <summary>
  81. /// Occurs when new message have been recieved.
  82. /// </summary>
  83. public event EventHandler<MessageRecievedEventArgs> MessageRecieved;
  84. /// <summary>
  85. /// Occurs when message is sent
  86. /// </summary>
  87. public event EventHandler<AsyncCompletedEventArgs> SendCompleted;
  88. /// <summary>
  89. /// Indicates if client is connected to message server.
  90. /// </summary>
  91. public bool Connected
  92. {
  93. get
  94. {
  95. return this.socket.Connected;
  96. }
  97. }
  98. /// <summary>
  99. /// Connect to message server async.
  100. /// </summary>
  101. /// <param name="state">
  102. /// </param>
  103. public void ConnectAsync()
  104. {
  105. this.ConnectAsync(null);
  106. }
  107. /// <summary>
  108. /// Connect to message server async.
  109. /// </summary>
  110. /// <param name="state">
  111. /// </param>
  112. public void ConnectAsync(object state)
  113. {
  114. if (!this.Connected)
  115. {
  116. var endPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, this.port);
  117. var args = new SocketAsyncEventArgs { UserToken = state, RemoteEndPoint = endPoint };
  118. args.Completed += this.OnSocketConnected;
  119. this.socket.ConnectAsync(args);
  120. }
  121. }
  122. /// <summary>
  123. /// Disconnect from message server.
  124. /// </summary>
  125. public void Disconnect()
  126. {
  127. this.socket.Close();
  128. }
  129. /// <summary>
  130. /// Send message.
  131. /// </summary>
  132. /// <param name="message">
  133. /// </param>
  134. public void SendMessageAsync(Message message)
  135. {
  136. this.SendMessageAsync(message, null);
  137. }
  138. /// <summary>
  139. /// Send message.
  140. /// </summary>
  141. /// <param name="message">
  142. /// </param>
  143. /// <param name="userState">
  144. /// </param>
  145. public void SendMessageAsync(Message message, object userState)
  146. {
  147. if ((this.socket == null) || (this.Connected == false))
  148. {
  149. // TODO : throw exception.
  150. }
  151. var args = new SocketAsyncEventArgs();
  152. byte[] serializedMessage = this.messageSerializer.Serialize(message);
  153. List<byte> messageByteList = serializedMessage.ToList();
  154. for (int i = 1023; i < serializedMessage.Length; i += 1023)
  155. {
  156. messageByteList.Insert(i, 0);
  157. i++;
  158. }
  159. messageByteList.Add(1);
  160. args.SetBuffer(messageByteList.ToArray(), 0, messageByteList.Count);
  161. args.Completed += this.SocketSendCompleted;
  162. args.UserToken = userState;
  163. this.socket.SendAsync(args);
  164. }
  165. /// <summary>
  166. /// </summary>
  167. /// <param name="e">
  168. /// </param>
  169. private void OnConnected(AsyncCompletedEventArgs e)
  170. {
  171. EventHandler<AsyncCompletedEventArgs> handler = this.ConnectCompleted;
  172. if (handler != null)
  173. {
  174. handler(this, e);
  175. }
  176. }
  177. /// <summary>
  178. /// </summary>
  179. /// <param name="e">
  180. /// </param>
  181. private void OnConnectionLost()
  182. {
  183. EventHandler<EventArgs> handler = this.ConnectionLost;
  184. if (handler != null)
  185. {
  186. handler(this, new EventArgs());
  187. }
  188. }
  189. /// <summary>
  190. /// </summary>
  191. /// <param name="e">
  192. /// </param>
  193. private void OnMessageRecieved(MessageRecievedEventArgs e)
  194. {
  195. EventHandler<MessageRecievedEventArgs> handler = this.MessageRecieved;
  196. if (handler != null)
  197. {
  198. handler(this, e);
  199. }
  200. }
  201. /// <summary>
  202. /// </summary>
  203. /// <param name="e">
  204. /// </param>
  205. private void OnSendCompleted(AsyncCompletedEventArgs e)
  206. {
  207. EventHandler<AsyncCompletedEventArgs> handler = this.SendCompleted;
  208. if (handler != null)
  209. {
  210. handler(this, e);
  211. }
  212. }
  213. /// <summary>
  214. /// </summary>
  215. /// <param name="sender">
  216. /// </param>
  217. /// <param name="e">
  218. /// </param>
  219. private void OnSocketConnected(object sender, SocketAsyncEventArgs e)
  220. {
  221. AsyncCompletedEventArgs asyncArgs;
  222. if (this.Connected)
  223. {
  224. var response = new byte[1024];
  225. e.SetBuffer(response, 0, response.Length);
  226. e.Completed -= this.OnSocketConnected;
  227. e.Completed += this.OnSocketReceive;
  228. this.socket.ReceiveAsync(e);
  229. asyncArgs = new AsyncCompletedEventArgs(null, false, e.UserToken);
  230. this.OnConnected(asyncArgs);
  231. }
  232. // TODO: Handle error while connection.
  233. }
  234. /// <summary>
  235. /// </summary>
  236. /// <param name="sender">
  237. /// </param>
  238. /// <param name="e">
  239. /// </param>
  240. private void OnSocketReceive(object sender, SocketAsyncEventArgs e)
  241. {
  242. if (e.BytesTransferred == 0)
  243. {
  244. this.OnConnectionLost();
  245. this.socket.Close();
  246. return;
  247. }
  248. this.messageBuffer.AddRange(e.Buffer.Take(e.BytesTransferred - 1));
  249. if (e.Buffer[e.BytesTransferred - 1] > 0)
  250. {
  251. this.OnMessageRecieved(
  252. new MessageRecievedEventArgs(this.messageSerializer.Deserialize(this.messageBuffer.ToArray())));
  253. this.messageBuffer.Clear();
  254. }
  255. this.socket.ReceiveAsync(e);
  256. }
  257. /// <summary>
  258. /// </summary>
  259. /// <param name="sender">
  260. /// </param>
  261. /// <param name="e">
  262. /// </param>
  263. private void SocketSendCompleted(object sender, SocketAsyncEventArgs e)
  264. {
  265. if (e.SocketError == SocketError.Success)
  266. {
  267. this.OnSendCompleted(new AsyncCompletedEventArgs(null, false, e.UserToken));
  268. }
  269. // TODO: Handle error if send is not successful.
  270. }
  271. }
  272. }