using System; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.WebSockets; namespace WebSocketEcho { /// /// Echo 的摘要说明 /// public class Echo : IHttpHandler { // list of client WebSockets that are open private static readonly IList Clients = new List(); // ensure thread-safety of the WebSocket clients private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); public void ProcessRequest(HttpContext context) { if (context.IsWebSocketRequest) context.AcceptWebSocketRequest(ProcessSocketRequest); } private async Task ProcessSocketRequest(AspNetWebSocketContext context) { var socket = context.WebSocket; // add socket to socket list Locker.EnterWriteLock(); try { Clients.Add(socket); } finally { Locker.ExitWriteLock(); } // maintain socket while (true) { var array = new byte[1024]; var buffer = new ArraySegment(array); // async wait for a change in the socket var result = await socket.ReceiveAsync(buffer, CancellationToken.None); if (socket.State == WebSocketState.Open) { // echo to all clients foreach (var client in Clients) { var seg = new ArraySegment(array, 0, result.Count); await client.SendAsync(seg, WebSocketMessageType.Text, true, CancellationToken.None); } } else { // client is no longer available - delete from list Locker.EnterWriteLock(); try { Clients.Remove(socket); } finally { Locker.ExitWriteLock(); } break; } } } public bool IsReusable { get { return false; } } } }