1.新建Netcore Web项目
2.创建简易通讯协议
public class MsgTemplate ???{ ???????public string SenderID { get; set; } ???????public string ReceiverID { get; set; } ???????public string MessageType { get; set; } ???????public string Content { get; set; } ???}
SenderID发送者ID
ReceiverID 接受者ID
MessageType 消息类型 Text Voice 等等
Content 消息内容
3.添加中间件ChatWebSocketMiddleware
?1 public class ChatWebSocketMiddleware ?2 ????{ ?3 ????????private static ConcurrentDictionary<string, System.Net.WebSockets.WebSocket> _sockets = new ConcurrentDictionary<string, System.Net.WebSockets.WebSocket>(); ?4 ??5 ????????private readonly RequestDelegate _next; ?6 ??7 ????????public ChatWebSocketMiddleware(RequestDelegate next) ?8 ????????{ ?9 ????????????_next = next; 10 ????????} 11 ?12 ????????public async Task Invoke(HttpContext context) 13 ????????{ 14 ????????????if (!context.WebSockets.IsWebSocketRequest) 15 ????????????{ 16 ????????????????await _next.Invoke(context); 17 ????????????????return; 18 ????????????} 19 ????????????System.Net.WebSockets.WebSocket dummy; 20 ?21 ????????????CancellationToken ct = context.RequestAborted; 22 ????????????var currentSocket = await context.WebSockets.AcceptWebSocketAsync(); 23 ????????????//string socketId = Guid.NewGuid().ToString(); 24 ????????????string socketId = context.Request.Query["sid"].ToString(); 25 ????????????if (!_sockets.ContainsKey(socketId)) 26 ????????????{ 27 ????????????????_sockets.TryAdd(socketId, currentSocket); 28 ????????????} 29 ????????????//_sockets.TryRemove(socketId, out dummy); 30 ????????????//_sockets.TryAdd(socketId, currentSocket); 31 ?32 ????????????while (true) 33 ????????????{ 34 ????????????????if (ct.IsCancellationRequested) 35 ????????????????{ 36 ????????????????????break; 37 ????????????????} 38 ?39 ????????????????string response = await ReceiveStringAsync(currentSocket, ct); 40 ????????????????MsgTemplate msg = JsonConvert.DeserializeObject<MsgTemplate>(response); 41 ?42 ????????????????if (string.IsNullOrEmpty(response)) 43 ????????????????{ 44 ????????????????????if (currentSocket.State != WebSocketState.Open) 45 ????????????????????{ 46 ????????????????????????break; 47 ????????????????????} 48 ?49 ????????????????????continue; 50 ????????????????} 51 ?52 ????????????????foreach (var socket in _sockets) 53 ????????????????{ 54 ????????????????????if (socket.Value.State != WebSocketState.Open) 55 ????????????????????{ 56 ????????????????????????continue; 57 ????????????????????} 58 ????????????????????if (socket.Key == msg.ReceiverID || socket.Key == socketId) 59 ????????????????????{ 60 ????????????????????????await SendStringAsync(socket.Value, JsonConvert.SerializeObject(msg), ct); 61 ????????????????????} 62 ????????????????} 63 ????????????} 64 ?65 ????????????//_sockets.TryRemove(socketId, out dummy); 66 ?67 ????????????await currentSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct); 68 ????????????currentSocket.Dispose(); 69 ????????} 70 ?71 ????????private static Task SendStringAsync(System.Net.WebSockets.WebSocket socket, string data, CancellationToken ct = default(CancellationToken)) 72 ????????{ 73 ????????????var buffer = Encoding.UTF8.GetBytes(data); 74 ????????????var segment = new ArraySegment<byte>(buffer); 75 ????????????return socket.SendAsync(segment, WebSocketMessageType.Text, true, ct); 76 ????????} 77 ?78 ????????private static async Task<string> ReceiveStringAsync(System.Net.WebSockets.WebSocket socket, CancellationToken ct = default(CancellationToken)) 79 ????????{ 80 ????????????var buffer = new ArraySegment<byte>(new byte[8192]); 81 ????????????using (var ms = new MemoryStream()) 82 ????????????{ 83 ????????????????WebSocketReceiveResult result; 84 ????????????????do 85 ????????????????{ 86 ????????????????????ct.ThrowIfCancellationRequested(); 87 ?88 ????????????????????result = await socket.ReceiveAsync(buffer, ct); 89 ????????????????????ms.Write(buffer.Array, buffer.Offset, result.Count); 90 ????????????????} 91 ????????????????while (!result.EndOfMessage); 92 ?93 ????????????????ms.Seek(0, SeekOrigin.Begin); 94 ????????????????if (result.MessageType != WebSocketMessageType.Text) 95 ????????????????{ 96 ????????????????????return null; 97 ????????????????} 98 ?99 ????????????????using (var reader = new StreamReader(ms, Encoding.UTF8))100 ????????????????{101 ????????????????????return await reader.ReadToEndAsync();102 ????????????????}103 ????????????}104 ????????}105 ????}
控制只有接收者才能收到消息if (socket.Key == msg.ReceiverID || socket.Key == socketId){ ????await SendStringAsync(socket.Value,JsonConvert.SerializeObject(msg), ct);}
4.在Startup.cs中使用中间件
app.UseWebSockets();app.UseMiddleware<ChatWebSocketMiddleware>();
5.建立移动端测试示例 这里采用Ionic3运行在web端
创建ionic3项目略过 新手可点这里查看 或者有Angular2/4项目经验的可直接往下看
(1) 启动Ionic项目
当初创建ionic3项目时候遇到不少问题
比如ionic-cli初始化项目失败 切换到默认npmorg源就好了
比如ionic serve失败 打开代理允许FQ就好了
启动后界面是这样式的
(2) 创建聊天窗口dialog 具体布局实现 模块加载略过 直接进入websocket实现
在这之前别忘了启动web项目 否则会出现这样情况 链接不到服务
(3)dialog.ts具体实现
export class Dialog { ???private ws: any; ???private msgArr: Array<any>; ???constructor(private httpService: HttpService) { ???????this.msgArr = []; ???} ???ionViewDidEnter() { ???????if (!this.ws) { ???????????this.ws = new WebSocket("ws://localhost:56892?sid=222"); ???????????this.ws.onopen = () => { ???????????????console.log(‘open‘); ???????????}; ???????????this.ws.onmessage = (event) => { ???????????????console.log(‘new message: ‘ + event.data); ???????????????var msgObj = JSON.parse(event.data); ???????????????this.msgArr.push(msgObj);; ???????????}; ???????????this.ws.onerror = () => { ???????????????console.log(‘error occurred!‘); ???????????}; ???????????this.ws.onclose = (event) => { ???????????????console.log(‘close code=‘ + event.code); ???????????}; ???????} ???} ???sendMsg(msg) {//msg为我要发送的内容 比如"hello world" ???????var msgObj = { ???????????SenderID: "222", ???????????ReceiverID: "111", ???????????MessageType: "text", ???????????Content: msg ???????}; ???????this.ws.send(JSON.stringify(msgObj)); ???}
ws://localhost:56892?sid=222 这是websocke服务链接地址
sid表示着我这个端的WebSocke唯一标识 找到这个key就可以找到我这个用户端了
6.在web端也实现一个会话窗口
<div class="container" style="width:90%;margin:0px auto;border:1px solid steelblue;"> ???<div class="msg"> ???????<div id="msgs" style="height:200px;"></div> ???</div> ???<div style="display:block;width:100%"> ???????<input type="text" style="max-width:unset;width:100%;max-width:100%" id="MessageField" placeholder="type message and press enter" /> ???</div></div>
<script> ???????$(function () { ???????????$(‘.navbar-default‘).addClass(‘on‘); ???????????var userName = ‘@Model‘; ???????????var protocol = location.protocol === "https:" ? "wss:" : "ws:"; ???????????var wsUri = protocol + "//" + window.location.host + "?sid=111"; ???????????var socket = new WebSocket(wsUri); ???????????socket.onopen = e => { ???????????????console.log("socket opened", e); ???????????}; ???????????socket.onclose = function (e) { ???????????????console.log("socket closed", e); ???????????}; ???????????socket.onmessage = function (e) { ???????????????console.log(e); ???????????????var msgObj = JSON.parse(e.data); ???????????????$(‘#msgs‘).append(msgObj.Content + ‘<br />‘); ???????????}; ???????????socket.onerror = function (e) { ???????????????console.error(e.data); ???????????}; ???????????$(‘#MessageField‘).keypress(function (e) { ???????????????if (e.which != 13) { ???????????????????return; ???????????????} ???????????????e.preventDefault(); ???????????????var message = $(‘#MessageField‘).val(); ???????????????var msgObj = { ???????????????????SenderID:"111", ???????????????????ReceiverID:"222", ???????????????????MessageType: "text", ???????????????????Content: message ???????????????}; ???????????????socket.send(JSON.stringify(msgObj)); ???????????????$(‘#MessageField‘).val(‘‘); ???????????}); ???????}); ???</script>
基本开发完成 接下来看看效果
7.web和webapp端对话
8.webapp发送 web接收
NetCore WebSocket 即时通讯示例
原文地址:https://www.cnblogs.com/Javi/p/9303022.html