Echo.ashx.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.WebSockets;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using System.Web;
  8. using System.Web.WebSockets;
  9. namespace WebSocketEcho
  10. {
  11. /// <summary>
  12. /// Echo 的摘要说明
  13. /// </summary>
  14. public class Echo : IHttpHandler
  15. {
  16. // list of client WebSockets that are open
  17. private static readonly IList<WebSocket> Clients = new List<WebSocket>();
  18. // ensure thread-safety of the WebSocket clients
  19. private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
  20. public void ProcessRequest(HttpContext context)
  21. {
  22. if (context.IsWebSocketRequest)
  23. context.AcceptWebSocketRequest(ProcessSocketRequest);
  24. }
  25. private async Task ProcessSocketRequest(AspNetWebSocketContext context)
  26. {
  27. var socket = context.WebSocket;
  28. // add socket to socket list
  29. Locker.EnterWriteLock();
  30. try
  31. {
  32. Clients.Add(socket);
  33. }
  34. finally
  35. {
  36. Locker.ExitWriteLock();
  37. }
  38. // maintain socket
  39. while (true)
  40. {
  41. var array = new byte[1024];
  42. var buffer = new ArraySegment<byte>(array);
  43. // async wait for a change in the socket
  44. var result = await socket.ReceiveAsync(buffer, CancellationToken.None);
  45. if (socket.State == WebSocketState.Open)
  46. {
  47. // echo to all clients
  48. foreach (var client in Clients)
  49. {
  50. var seg = new ArraySegment<byte>(array, 0, result.Count);
  51. await client.SendAsync(seg, WebSocketMessageType.Text, true, CancellationToken.None);
  52. }
  53. }
  54. else
  55. {
  56. // client is no longer available - delete from list
  57. Locker.EnterWriteLock();
  58. try
  59. {
  60. Clients.Remove(socket);
  61. }
  62. finally
  63. {
  64. Locker.ExitWriteLock();
  65. }
  66. break;
  67. }
  68. }
  69. }
  70. public bool IsReusable
  71. {
  72. get
  73. {
  74. return false;
  75. }
  76. }
  77. }
  78. }