TSocket.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using System;
  2. using System.Net.Sockets;
  3. namespace TNet
  4. {
  5. public class TSocketState
  6. {
  7. public Action Action { get; set; }
  8. public void Run()
  9. {
  10. this.Action();
  11. }
  12. }
  13. public class TSocket: IDisposable
  14. {
  15. private Socket socket;
  16. private readonly TPoller poller;
  17. private readonly SocketAsyncEventArgs innSocketAsyncEventArgs = new SocketAsyncEventArgs();
  18. private readonly SocketAsyncEventArgs outSocketAsyncEventArgs = new SocketAsyncEventArgs();
  19. private readonly TBuffer recvBuffer = new TBuffer();
  20. private readonly TBuffer sendBuffer = new TBuffer();
  21. public bool IsSending { get; private set; }
  22. public TSocket(TPoller poller)
  23. {
  24. this.poller = poller;
  25. this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  26. this.outSocketAsyncEventArgs.Completed += this.OnComplete;
  27. this.innSocketAsyncEventArgs.Completed += this.OnComplete;
  28. this.IsSending = false;
  29. }
  30. public void Dispose()
  31. {
  32. if (this.socket == null)
  33. {
  34. return;
  35. }
  36. socket.Dispose();
  37. this.socket = null;
  38. poller.CanWriteSocket.Remove(this);
  39. }
  40. public void Connect(string host, int port)
  41. {
  42. socket.ConnectAsync(this.innSocketAsyncEventArgs);
  43. }
  44. public int CanRecvSize
  45. {
  46. get
  47. {
  48. return this.recvBuffer.Count;
  49. }
  50. }
  51. public void Recv(byte[] buffer)
  52. {
  53. this.recvBuffer.RecvFrom(buffer);
  54. }
  55. public void Send(byte[] buffer)
  56. {
  57. this.sendBuffer.SendTo(buffer);
  58. // 如果正在发送,则不做可发送标记
  59. if (this.IsSending)
  60. {
  61. return;
  62. }
  63. if (this.poller.CanWriteSocket.Contains(this))
  64. {
  65. return;
  66. }
  67. this.poller.CanWriteSocket.Add(this);
  68. }
  69. private void OnComplete(object sender, SocketAsyncEventArgs e)
  70. {
  71. Action action = () => { };
  72. switch (e.LastOperation)
  73. {
  74. case SocketAsyncOperation.Accept:
  75. break;
  76. case SocketAsyncOperation.Connect:
  77. action = this.OnConnComplete;
  78. break;
  79. case SocketAsyncOperation.Disconnect:
  80. break;
  81. case SocketAsyncOperation.Receive:
  82. action = () => this.OnRecvComplete(e.BytesTransferred);
  83. break;
  84. case SocketAsyncOperation.Send:
  85. action = () => this.OnSendComplete(e.BytesTransferred);
  86. break;
  87. default:
  88. throw new ArgumentOutOfRangeException();
  89. }
  90. TSocketState socketState = new TSocketState
  91. {
  92. Action = action,
  93. };
  94. this.poller.Add(socketState);
  95. }
  96. private void OnConnComplete()
  97. {
  98. this.BeginRecv();
  99. }
  100. private void OnRecvComplete(int bytesTransferred)
  101. {
  102. this.recvBuffer.LastIndex += bytesTransferred;
  103. if (this.recvBuffer.LastIndex == TBuffer.ChunkSize)
  104. {
  105. this.recvBuffer.LastIndex = 0;
  106. this.recvBuffer.AddLast();
  107. }
  108. this.BeginRecv();
  109. }
  110. private void OnSendComplete(int bytesTransferred)
  111. {
  112. this.sendBuffer.FirstIndex += bytesTransferred;
  113. if (this.sendBuffer.FirstIndex == TBuffer.ChunkSize)
  114. {
  115. this.sendBuffer.FirstIndex = 0;
  116. this.sendBuffer.RemoveFirst();
  117. }
  118. // 如果没有数据可以发送,则返回
  119. if (this.sendBuffer.Count == 0)
  120. {
  121. this.IsSending = false;
  122. return;
  123. }
  124. // 继续发送数据
  125. this.BeginSend();
  126. }
  127. private void BeginRecv()
  128. {
  129. this.innSocketAsyncEventArgs.SetBuffer(this.recvBuffer.Last, this.recvBuffer.LastIndex, TBuffer.ChunkSize - this.recvBuffer.LastIndex);
  130. this.socket.ReceiveAsync(this.innSocketAsyncEventArgs);
  131. }
  132. public void BeginSend()
  133. {
  134. this.IsSending = true;
  135. int count = 0;
  136. if (TBuffer.ChunkSize - this.sendBuffer.FirstIndex < this.sendBuffer.Count)
  137. {
  138. count = TBuffer.ChunkSize - this.sendBuffer.FirstIndex;
  139. }
  140. else
  141. {
  142. count = this.sendBuffer.Count;
  143. }
  144. this.outSocketAsyncEventArgs.SetBuffer(this.sendBuffer.First, this.sendBuffer.FirstIndex, count);
  145. this.socket.SendAsync(outSocketAsyncEventArgs);
  146. }
  147. }
  148. }