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.

389 lines
11 KiB

  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using System.IO;
  8. using Apewer.Internals;
  9. using Apewer;
  10. namespace Apewer.Network
  11. {
  12. /// <summary>TCP 服务端。</summary>
  13. public class TcpServer
  14. {
  15. #region event
  16. /// <summary>Exception。</summary>
  17. public event Event<Exception> Excepted;
  18. /// <summary>服务端已启动。</summary>
  19. public event SocketEndPointEventHandler Started;
  20. /// <summary>服务端已关闭。</summary>
  21. public event SocketEndPointEventHandler Quitted;
  22. /// <summary>客户端已连接。</summary>
  23. public event SocketEndPointEventHandler Connected;
  24. /// <summary>客户端已断开。</summary>
  25. public event SocketEndPointEventHandler Closed;
  26. /// <summary>已收到客户端数据。</summary>
  27. public event SocketReceivedEventHandler Received;
  28. #region raise
  29. internal void RaiseExcepted(Exception exception)
  30. {
  31. if (Excepted != null) Excepted(this, exception);
  32. }
  33. internal void RaiseStarted()
  34. {
  35. if (Started != null)
  36. {
  37. var ip = _endpoint == null ? "" : _endpoint.Address.ToString();
  38. var port = _endpoint == null ? 0 : _endpoint.Port;
  39. Started(this, ip, port);
  40. }
  41. }
  42. internal void RaiseConnected(string ip, int port)
  43. {
  44. if (Connected != null) Connected(this, ip, port);
  45. }
  46. internal void RaiseClosed(string ip, int port)
  47. {
  48. if (Closed != null) Closed(this, ip, port);
  49. }
  50. internal void RaiseQuitted()
  51. {
  52. if (Quitted != null)
  53. {
  54. var ip = _endpoint == null ? "" : _endpoint.Address.ToString();
  55. var port = _endpoint == null ? 0 : _endpoint.Port;
  56. Quitted(this, ip, port);
  57. }
  58. }
  59. internal void RaiseReceived(string ip, int port, byte[] bytes)
  60. {
  61. if (Received != null) Received(this, ip, port, bytes);
  62. }
  63. #endregion
  64. #endregion
  65. #region definition
  66. private Socket _socket = null;
  67. private Thread _listener = null;
  68. private SortedList _client = null;
  69. private IPEndPoint _endpoint = null;
  70. private int _port = 0;
  71. private int _max = 0;
  72. private int _timeout = 0;
  73. private bool _state = false;
  74. private bool _background = true;
  75. /// <summary>构造函数。</summary>
  76. public TcpServer(int port = 0)
  77. {
  78. Port = port;
  79. Max = 1000;
  80. Timeout = 1000;
  81. }
  82. #endregion
  83. #region accessor
  84. /// <summary>获取或设置监听线程是否为后台线程,默认为“是”。</summary>
  85. public bool Background
  86. {
  87. get { return _background; }
  88. set
  89. {
  90. _background = value;
  91. try { if (_listener != null) _listener.IsBackground = value; }
  92. catch (Exception argex) { RaiseExcepted(argex); }
  93. }
  94. }
  95. /// <summary>端口。</summary>
  96. public int Port
  97. {
  98. get
  99. {
  100. int vr = _port;
  101. if (vr > 65535) vr = 65535;
  102. if (vr < 0) vr = 0;
  103. return vr;
  104. }
  105. set
  106. {
  107. int vport = value;
  108. if (vport < 0) vport = 0;
  109. if (vport > 65535) vport = 65535;
  110. _port = vport;
  111. }
  112. }
  113. /// <summary>最大客户端数量。</summary>
  114. public int Max
  115. {
  116. get { return _max; }
  117. set { _max = (value > 0) ? value : 0; }
  118. }
  119. /// <summary>发送数据和接收数据的超时时间。</summary>
  120. public int Timeout
  121. {
  122. get { return _timeout; }
  123. set { _timeout = (value > 0) ? value : 0; }
  124. }
  125. /// <summary>服务端正在运行。</summary>
  126. public bool Alive
  127. {
  128. get { return (_listener != null) ? _listener.IsAlive : false; }
  129. }
  130. /// <summary>已连接的客户端数量。</summary>
  131. public int Count
  132. {
  133. get { return (_client != null) ? _client.Count : 0; }
  134. }
  135. /// <summary>启动服务端。</summary>
  136. public bool Start()
  137. {
  138. try
  139. {
  140. _endpoint = new IPEndPoint(IPAddress.Any, Port);
  141. _client = new SortedList();
  142. _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  143. _socket.Bind(_endpoint);
  144. _socket.Listen(Max);
  145. _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.AcceptConnection, 1);
  146. _socket.ReceiveTimeout = Timeout;
  147. _socket.SendTimeout = Timeout;
  148. _listener = new Thread(Listener);
  149. _listener.IsBackground = Background;
  150. _listener.Start();
  151. _state = _listener.IsAlive;
  152. var vcep = (IPEndPoint)_socket.LocalEndPoint;
  153. _port = vcep.Port;
  154. RaiseStarted();
  155. return true;
  156. }
  157. catch (Exception argex)
  158. {
  159. _endpoint = null;
  160. RaiseExcepted(argex);
  161. if ((_socket != null) && _socket.Connected) _socket.Close();
  162. Quit();
  163. return false;
  164. }
  165. }
  166. /// <summary>关闭服务端。</summary>
  167. public void Quit()
  168. {
  169. Quit(true);
  170. }
  171. /// <summary>断开与所有客户端的连接。</summary>
  172. public void Close()
  173. {
  174. if (_client != null)
  175. {
  176. foreach (Socket vcs in _client.Values)
  177. {
  178. try
  179. {
  180. var vep = (IPEndPoint)vcs.RemoteEndPoint;
  181. Close(vep.Address.ToString(), vep.Port);
  182. }
  183. catch (Exception argex)
  184. {
  185. RaiseExcepted(argex);
  186. }
  187. }
  188. }
  189. }
  190. /// <summary>断开与指定客户端的连接。</summary>
  191. public void Close(string ip, int port)
  192. {
  193. int vport = port;
  194. if (vport < 0) vport = 0;
  195. if (vport > 65535) vport = 65535;
  196. if (!string.IsNullOrEmpty(ip))
  197. {
  198. var vck = ip + ":" + vport.ToString();
  199. var vcs = Client(ip, vport);
  200. try
  201. {
  202. if (vcs != null) vcs.Close();
  203. Remove(vck);
  204. RaiseClosed(ip, vport);
  205. }
  206. catch (Exception argex)
  207. {
  208. RaiseExcepted(argex);
  209. }
  210. }
  211. }
  212. /// <summary>向所有客户端广播数据。</summary>
  213. public void Send(byte[] bytes)
  214. {
  215. var vl = bytes.Length;
  216. if ((_client.Count > 0) && (vl > 0))
  217. {
  218. foreach (Socket i in _client.Values) Send(bytes, i);
  219. }
  220. }
  221. /// <summary>向指定客户端发送数据。</summary>
  222. public bool Send(byte[] bytes, string ip, int port)
  223. {
  224. int vport = port;
  225. if (vport < 0) vport = 0;
  226. if (vport > 65535) vport = 65535;
  227. if (string.IsNullOrEmpty(ip)) return false;
  228. return Send(bytes, Client(ip, port));
  229. }
  230. #endregion
  231. #region logic
  232. /// <summary>
  233. ///
  234. /// </summary>
  235. /// <param name="event"></param>
  236. private void Quit(bool @event)
  237. {
  238. Close();
  239. if (_listener != null)
  240. {
  241. if (_listener.IsAlive) _listener.Abort();
  242. _listener = null;
  243. }
  244. if (_socket != null)
  245. {
  246. _socket.Close();
  247. _socket = null;
  248. }
  249. if (_client != null)
  250. {
  251. _client.Clear();
  252. _client = null;
  253. }
  254. _endpoint = null;
  255. if (@event) RaiseQuitted();
  256. }
  257. private void Close(Socket socket)
  258. {
  259. if (socket != null)
  260. {
  261. try { socket.Close(); }
  262. catch (Exception argex) { RaiseExcepted(argex); }
  263. }
  264. }
  265. internal void Remove(string key)
  266. {
  267. if ((_client != null) && (!string.IsNullOrEmpty(key)))
  268. {
  269. if (_client.ContainsKey(key))
  270. {
  271. try
  272. {
  273. Close((Socket)_client[key]);
  274. _client.Remove(key);
  275. }
  276. catch (Exception argex)
  277. {
  278. RaiseExcepted(argex);
  279. }
  280. }
  281. }
  282. }
  283. private bool Send(byte[] bytes, Socket client)
  284. {
  285. var vl = bytes.Length;
  286. if ((client != null) && (vl > 0))
  287. {
  288. try
  289. {
  290. return (client.Send(bytes, vl, SocketFlags.None) > 0) ? true : false;
  291. }
  292. catch (Exception argex) { RaiseExcepted(argex); }
  293. }
  294. return false;
  295. }
  296. private void Listener()
  297. {
  298. while (_socket != null)
  299. {
  300. try
  301. {
  302. var vcs = _socket.Accept();
  303. if (vcs != null)
  304. {
  305. var vep = (IPEndPoint)vcs.RemoteEndPoint;
  306. var vck = vep.Address.ToString() + ":" + vep.Port.ToString();
  307. _client.Add(vck, vcs);
  308. var vci = new TcpInstance(this, _socket, vcs);
  309. var vct = new Thread(vci.Process);
  310. vct.IsBackground = true;
  311. vct.Name = vck;
  312. vct.Start();
  313. RaiseConnected(vep.Address.ToString(), vep.Port);
  314. }
  315. }
  316. catch (Exception argex)
  317. {
  318. RaiseExcepted(argex);
  319. }
  320. }
  321. Quit(false);
  322. }
  323. private Socket Client(string ip, int port)
  324. {
  325. int vport = port;
  326. if (vport < 0) vport = 0;
  327. if (vport > 65535) vport = 65535;
  328. try
  329. {
  330. var vck = ip + ":" + vport.ToString();
  331. if (_client.ContainsKey(vck)) return (Socket)_client[vck];
  332. }
  333. catch (Exception argex)
  334. {
  335. RaiseExcepted(argex);
  336. }
  337. return null;
  338. }
  339. #endregion
  340. }
  341. }