WSClientProvider.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System;
  2. using System.Text;
  3. using System.Threading;
  4. namespace IFramework.Net.WebSocket
  5. {
  6. using IFramework.Net.Tcp;
  7. internal class WSClientProvider : IDisposable, IWSClientProvider
  8. {
  9. TcpClientProvider clientProvider = null;
  10. private Encoding encoding = Encoding.UTF8;
  11. ManualResetEvent resetEvent = new ManualResetEvent(false);
  12. int waitingTimeout = 1000 * 60 * 30;
  13. public bool IsConnected { get; private set; }
  14. AcceptInfo acceptInfo = null;
  15. public OnDisconnectedHandler OnDisconnected{ get; set; }
  16. public OnConnectedHandler OnConnected { get; set; }
  17. public OnReceivedHandler OnReceived { get; set; }
  18. public OnReceivedSegmentHandler OnReceivedBytes { get; set; }
  19. public OnSentHandler OnSent { get; set; }
  20. public WSClientProvider(int bufferSize=4096,int blocks=8)
  21. {
  22. clientProvider = new TcpClientProvider(bufferSize, blocks);
  23. clientProvider.DisconnectedCallback = new OnDisconnectedHandler(DisconnectedHandler);
  24. clientProvider.ReceivedOffsetCallback = new OnReceivedSegmentHandler(ReceivedHanlder);
  25. clientProvider.SentCallback = new OnSentHandler(SentHandler);
  26. }
  27. public void Dispose()
  28. {
  29. resetEvent.Dispose();
  30. }
  31. public static WSClientProvider CreateProvider(int bufferSize = 4096, int blocks = 8)
  32. {
  33. return new WSClientProvider(bufferSize,blocks);
  34. }
  35. /// <summary>
  36. /// wsUrl:ws://ip:port
  37. /// </summary>
  38. /// <param name="wsUrl"></param>
  39. /// <returns></returns>
  40. public bool Connect(string wsUrl)
  41. {
  42. Random rand = new Random(DateTime.Now.Millisecond);
  43. WSConnectionItem wsItem = new WSConnectionItem(wsUrl);
  44. bool isOk = clientProvider.ConnectTo(wsItem.Port, wsItem.Domain);
  45. if (isOk == false) throw new Exception("连接失败...");
  46. string req = new AccessInfo()
  47. {
  48. Host = wsItem.Host,
  49. Origin = "http://" + wsItem.Host,
  50. SecWebSocketKey = Convert.ToBase64String(encoding.GetBytes(wsUrl + rand.Next(100, 100000).ToString()))
  51. }.ToString();
  52. isOk = clientProvider.Send(new SegmentOffset(encoding.GetBytes(req)));
  53. resetEvent.WaitOne(waitingTimeout);
  54. return IsConnected;
  55. }
  56. public bool Connect(WSConnectionItem wsUrl)
  57. {
  58. return Connect(wsUrl);
  59. }
  60. public bool Send(string msg,bool waiting=true)
  61. {
  62. if (IsConnected == false) return false;
  63. var buf = new WebsocketFrame().ToSegmentFrame(msg);
  64. clientProvider.Send(buf,waiting);
  65. return true;
  66. }
  67. public bool Send(SegmentOffset data,bool waiting=true)
  68. {
  69. if (IsConnected == false) return false;
  70. clientProvider.Send(data,waiting);
  71. return true;
  72. }
  73. public void SendPong(SegmentOffset buf)
  74. {
  75. var seg = new WebsocketFrame().ToSegmentFrame(buf,OpCodeType.Bong);
  76. clientProvider.Send(seg, true);
  77. }
  78. public void SendPing()
  79. {
  80. var buf = new WebsocketFrame().ToSegmentFrame(new byte[] { },OpCodeType.Bing);
  81. clientProvider.Send(buf, true);
  82. }
  83. private void DisconnectedHandler(SocketToken sToken)
  84. {
  85. IsConnected = false;
  86. if (OnDisconnected != null) OnDisconnected(sToken);
  87. }
  88. private void ReceivedHanlder(SegmentToken session)
  89. {
  90. if (IsConnected == false)
  91. {
  92. string msg = encoding.GetString(session.Data.buffer, session.Data.offset, session.Data.size);
  93. acceptInfo = new WebsocketFrame().ParseAcceptedFrame(msg);
  94. if ((IsConnected = acceptInfo.IsHandShaked()))
  95. {
  96. resetEvent.Set();
  97. if (OnConnected != null) OnConnected(session.sToken, IsConnected);
  98. }
  99. else
  100. {
  101. clientProvider.Disconnect();
  102. }
  103. }
  104. else
  105. {
  106. WebsocketFrame packet = new WebsocketFrame();
  107. bool isOk= packet.DecodingFromBytes(session.Data, true);
  108. if (isOk == false) return;
  109. if (packet.OpCode == 0x01)
  110. {
  111. if (OnReceived != null)
  112. OnReceived(session.sToken, encoding.GetString(packet.Payload.buffer,
  113. packet.Payload.offset, packet.Payload.size));
  114. return;
  115. }
  116. else if (packet.OpCode == 0x08)//close
  117. {
  118. IsConnected = false;
  119. clientProvider.Disconnect();
  120. }
  121. else if (packet.OpCode == 0x09)//ping
  122. {
  123. SendPong(session.Data);
  124. }
  125. else if (packet.OpCode == 0x0A)//pong
  126. {
  127. SendPing();
  128. }
  129. if (OnReceivedBytes != null && packet.Payload.size > 0)
  130. OnReceivedBytes(new SegmentToken(session.sToken, packet.Payload));
  131. }
  132. }
  133. private void SentHandler(SegmentToken session)
  134. {
  135. if (OnSent!=null){
  136. OnSent(session);
  137. }
  138. }
  139. //private void ConnectedHandler(SocketToken sToken,bool isConnected)
  140. //{
  141. //}
  142. }
  143. }