TcpAcceptor.cs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Threading.Tasks;
  5. namespace TNet
  6. {
  7. public class TcpAcceptor: IDisposable
  8. {
  9. private readonly Socket socket;
  10. private readonly SocketAsyncEventArgs asyncEventArgs = new SocketAsyncEventArgs();
  11. public TcpAcceptor(string ip, ushort port, int backLog = 100)
  12. {
  13. this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  14. this.asyncEventArgs.Completed += OnArgsCompletion;
  15. this.socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
  16. this.socket.Listen(backLog);
  17. }
  18. public void Dispose()
  19. {
  20. this.socket.Dispose();
  21. }
  22. /// <summary>
  23. /// SocketAsyncEventArgs Accept回调函数,回调可能已经到了另外的线程
  24. /// </summary>
  25. /// <returns></returns>
  26. public Task<NetworkStream> AcceptAsync()
  27. {
  28. var tcs = new TaskCompletionSource<NetworkStream>();
  29. try
  30. {
  31. this.asyncEventArgs.UserToken = tcs;
  32. bool ret = this.socket.AcceptAsync(this.asyncEventArgs);
  33. if (!ret)
  34. {
  35. if (this.asyncEventArgs.SocketError == SocketError.Success)
  36. {
  37. var acceptSocket = this.asyncEventArgs.AcceptSocket;
  38. this.asyncEventArgs.AcceptSocket = null;
  39. return Task.FromResult(new NetworkStream(acceptSocket, true));
  40. }
  41. tcs.TrySetException(
  42. new InvalidOperationException(
  43. this.asyncEventArgs.SocketError.ToString()));
  44. }
  45. }
  46. catch (Exception ex)
  47. {
  48. tcs.TrySetException(ex);
  49. }
  50. return tcs.Task;
  51. }
  52. private static void OnArgsCompletion(object sender, SocketAsyncEventArgs e)
  53. {
  54. var tcs = (TaskCompletionSource<NetworkStream>) e.UserToken;
  55. if (e.SocketError != SocketError.Success)
  56. {
  57. tcs.TrySetException(new InvalidOperationException(e.SocketError.ToString()));
  58. return;
  59. }
  60. var acceptSocket = e.AcceptSocket;
  61. e.AcceptSocket = null;
  62. tcs.SetResult(new NetworkStream(acceptSocket, true));
  63. }
  64. }
  65. }