乘风原创程序

  • NetCore WebSocket即时通讯示例
  • 2020/6/23 9:29:49
  • NetCore WebSocket 即时通讯示例,供大家参考,具体内容如下

    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

    public class ChatWebSocketMiddleware
     {
     private static ConcurrentDictionary<string, System.Net.WebSockets.WebSocket> _sockets = new ConcurrentDictionary<string, System.Net.WebSockets.WebSocket>();
    
     private readonly RequestDelegate _next;
    
     public ChatWebSocketMiddleware(RequestDelegate next)
     {
     _next = next;
     }
    
     public async Task Invoke(HttpContext context)
     {
     if (!context.WebSockets.IsWebSocketRequest)
     {
     await _next.Invoke(context);
     return;
     }
     System.Net.WebSockets.WebSocket dummy;
    
     CancellationToken ct = context.RequestAborted;
     var currentSocket = await context.WebSockets.AcceptWebSocketAsync();
     //string socketId = Guid.NewGuid().ToString();
     string socketId = context.Request.Query["sid"].ToString();
     if (!_sockets.ContainsKey(socketId))
     {
     _sockets.TryAdd(socketId, currentSocket);
     }
     //_sockets.TryRemove(socketId, out dummy);
     //_sockets.TryAdd(socketId, currentSocket);
    
     while (true)
     {
     if (ct.IsCancellationRequested)
     {
      break;
     }
    
     string response = await ReceiveStringAsync(currentSocket, ct);
     MsgTemplate msg = JsonConvert.DeserializeObject<MsgTemplate>(response);
    
     if (string.IsNullOrEmpty(response))
     {
      if (currentSocket.State != WebSocketState.Open)
      {
      break;
      }
    
      continue;
     }
    
     foreach (var socket in _sockets)
     {
      if (socket.Value.State != WebSocketState.Open)
      {
      continue;
      }
      if (socket.Key == msg.ReceiverID || socket.Key == socketId)
      {
      await SendStringAsync(socket.Value, JsonConvert.SerializeObject(msg), ct);
      }
     }
     }
    
     //_sockets.TryRemove(socketId, out dummy);
    
     await currentSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct);
     currentSocket.Dispose();
     }
    
     private static Task SendStringAsync(System.Net.WebSockets.WebSocket socket, string data, CancellationToken ct = default(CancellationToken))
     {
     var buffer = Encoding.UTF8.GetBytes(data);
     var segment = new ArraySegment<byte>(buffer);
     return socket.SendAsync(segment, WebSocketMessageType.Text, true, ct);
     }
    
     private static async Task<string> ReceiveStringAsync(System.Net.WebSockets.WebSocket socket, CancellationToken ct = default(CancellationToken))
     {
     var buffer = new ArraySegment<byte>(new byte[8192]);
     using (var ms = new MemoryStream())
     {
     WebSocketReceiveResult result;
     do
     {
      ct.ThrowIfCancellationRequested();
    
      result = await socket.ReceiveAsync(buffer, ct);
      ms.Write(buffer.Array, buffer.Offset, result.Count);
     }
     while (!result.EndOfMessage);
    
     ms.Seek(0, SeekOrigin.Begin);
     if (result.MessageType != WebSocketMessageType.Text)
     {
      return null;
     }
    
     using (var reader = new StreamReader(ms, Encoding.UTF8))
     {
      return await reader.ReadToEndAsync();
     }
     }
     }
     }
    

    控制只有接收者才能收到消息

    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接收

    9.目前就实现了这么多  因为项目还涉及其它技术 暂时不开放源码了