TcpAcceptor.cs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. asyncEventArgs.UserToken = tcs;
  32. bool ret = this.socket.AcceptAsync(asyncEventArgs);
  33. if (!ret)
  34. {
  35. if (asyncEventArgs.SocketError == SocketError.Success)
  36. {
  37. var acceptSocket = asyncEventArgs.AcceptSocket;
  38. asyncEventArgs.AcceptSocket = null;
  39. return Task.FromResult(new NetworkStream(acceptSocket, true));
  40. }
  41. tcs.TrySetException(new InvalidOperationException(this.asyncEventArgs.SocketError.ToString()));
  42. }
  43. }
  44. catch (Exception ex)
  45. {
  46. tcs.TrySetException(ex);
  47. }
  48. return tcs.Task;
  49. }
  50. private static void OnArgsCompletion(object sender, SocketAsyncEventArgs e)
  51. {
  52. var tcs = (TaskCompletionSource<NetworkStream>)e.UserToken;
  53. if (e.SocketError != SocketError.Success)
  54. {
  55. tcs.TrySetException(new InvalidOperationException(e.SocketError.ToString()));
  56. return;
  57. }
  58. var acceptSocket = e.AcceptSocket;
  59. e.AcceptSocket = null;
  60. tcs.SetResult(new NetworkStream(acceptSocket, true));
  61. }
  62. }
  63. }