/// <summary> /// 发送消息到所有人 /// </summary> /// <param name="sockets"></param> /// <param name="arraySegment"></param> /// <returns></returns> public async static Task SendToWebSocketsAsync(List <WebSocket> sockets, DanmuData data) { SaveHistoricalMessg(data);//保存历史消息 var chatData = JsonConvert.SerializeObject(data); var buffer = Encoding.UTF8.GetBytes(chatData); ArraySegment <byte> arraySegment = new ArraySegment <byte>(buffer); //循环发送消息 for (int i = 0; i < sockets.Count; i++) { var tempsocket = sockets[i]; if (tempsocket.State == WebSocketState.Open) { //发送消息 await tempsocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None); } } }
public static List <DanmuData> historicalMessg = new List <DanmuData>();//存放历史消息 /// <summary> /// 接收请求 /// </summary> /// <param name="httpContext"></param> /// <param name="n"></param> /// <returns></returns> static async Task Acceptor(HttpContext httpContext, Func <Task> n) { if (!httpContext.WebSockets.IsWebSocketRequest) { return; } //建立一个WebSocket连接请求 var socket = await httpContext.WebSockets.AcceptWebSocketAsync(); //判断最大连接数 if (Sockets.Count >= 100) { await socket.CloseAsync(WebSocketCloseStatus.PolicyViolation, "连接超过最大限制 ...", CancellationToken.None); return; } lock (objLock) { Sockets.Add(socket);//加入 } var buffer = new byte[BufferSize]; //根据请求头获取 用户名 string userName = httpContext.Request.Query["userName"].ToString(); var danmu = new DanmuData(); //群发上线通知 // await SendToWebSocketsAsync(Sockets, chatData); while (true) { try { //建立连接,阻塞等待接收消息 var incoming = await socket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); //如果主动退出,则移除 if (incoming.MessageType == WebSocketMessageType.Close)//incoming.CloseStatus == WebSocketCloseStatus.EndpointUnavailable WebSocketCloseStatus.NormalClosure) { lock (objLock) { Sockets.Remove(socket);//移除 } // chatData = new ChatData() { info = userName + " 离开房间。还剩" + Sockets.Count + "人~~" }; // await SendToWebSocketsAsync(Sockets, chatData); break; //【注意】::这里一定要记得 跳出循环 (坑了好久) } //转字符串,然后序列化,然后赋值,然后再序列化 var chatDataStr = await ArraySegmentToStringAsync(new ArraySegment <byte>(buffer, 0, incoming.Count)); if (chatDataStr == "heartbeat")//如果是心跳检查,则直接跳过 { continue; } danmu = JsonConvert.DeserializeObject <DanmuData>(chatDataStr); await SendToWebSocketsAsync(Sockets.Where(t => t != socket).ToList(), danmu); } catch (Exception ex) //因为 nginx 没有数据传输 会自动断开 然后就会异常。 { Log(ex.Message); Sockets.Remove(socket);//移除 // chatData = new ChatData() { info = userName + " 离开房间。还剩" + Sockets.Count + "人~~" }; // await SendToWebSocketsAsync(Sockets, chatData); //【注意】::这里很重要 (如果不发送关闭会一直循环,且不能直接break。) await socket.CloseAsync(WebSocketCloseStatus.PolicyViolation, "未知异常 ...", CancellationToken.None); // 后面 就不走了? CloseAsync也不能 try 包起来? } } }