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.

401 lines
11 KiB

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