NetCore WebSocket 即时通讯示例

时间:2023-03-10 01:00:25
NetCore WebSocket 即时通讯示例

1.新建Netcore Web项目

NetCore WebSocket 即时通讯示例

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[]);
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(, 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项目

NetCore WebSocket 即时通讯示例

当初创建ionic3项目时候遇到不少问题

比如ionic-cli初始化项目失败 切换到默认npmorg源就好了

比如ionic serve失败 打开代理允许*就好了

启动后界面是这样式的

NetCore WebSocket 即时通讯示例

(2) 创建聊天窗口dialog  具体布局实现 模块加载略过 直接进入websocket实现

在这之前别忘了启动web项目 否则会出现这样情况 链接不到服务

NetCore WebSocket 即时通讯示例

(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: "",
ReceiverID: "",
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 != ) {
return;
} e.preventDefault(); var message = $('#MessageField').val(); var msgObj = {
SenderID:"",
ReceiverID:"",
MessageType: "text",
Content: message
};
socket.send(JSON.stringify(msgObj));
$('#MessageField').val('');
});
});
</script>

基本开发完成 接下来看看效果

7.web和webapp端对话

NetCore WebSocket 即时通讯示例

NetCore WebSocket 即时通讯示例

8.webapp发送  web接收

NetCore WebSocket 即时通讯示例

NetCore WebSocket 即时通讯示例

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