1. 程式人生 > >NetCore WebSocket 即時通訊示例

NetCore WebSocket 即時通訊示例

local doc acc code win ref 簡易 rem sync

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

技術分享

技術分享

9.目前就實現了這麽多 因為項目還涉及其它技術 暫時不開放源碼了

NetCore WebSocket 即時通訊示例