一共分为四步:
一、定于消息内容基类
namespace ReadJson_.Net6._0.WebSockets
{
/// <summary>
/// 消息基类模型
/// </summary>
public class MessageBase
{
/// <summary>
/// socket唯一ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 消息类型
/// </summary>
public int Type { get; set; }
/// <summary>
/// 消息信息
/// </summary>
public object Message { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public MessageBase(int type, object message)
{
Type = type;
Message = message;
}
/// <summary>
/// 构造函数
/// </summary>
public MessageBase(string id, int type, object message)
{
Id = id;
Type = type;
Message = message;
}
}
}
二、定义发送消息、监听消息 辅助类
using Newtonsoft.Json;
using ReadJson_.Net6._0.Model;
using System.Net.WebSockets;
using System.Text;
namespace ReadJson_.Net6._0.WebSockets
{
public class WebsocketHandlerMiddleware
{
/// <summary>
/// 消息事件委托
/// </summary>
/// <param name="message"></param>
public delegate void MessageEvent(MessageBase message);
/// <summary>
/// 消息事件集合
/// </summary>
private static readonly Dictionary<MessageType, List<MessageEvent>> dic = new Dictionary<MessageType, List<MessageEvent>>();
//存储所有的websocket连接
public static Dictionary<string, WebSocket> keyValues = new Dictionary<string, WebSocket>();
//读取管道配置
private readonly RequestDelegate _next;
/// <summary>
/// 构造
/// </summary>
/// <param name="next"></param>
public WebsocketHandlerMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// 项目启动初始化
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
string ip = context.Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
//仅当网页执行new WebSocket("ws://自己电脑ip:5068/ws")时,后台会执行此逻辑
if (context.WebSockets.IsWebSocketRequest)
{
//后台成功接收到连接请求并建立连接后,前台的webSocket.onopen = function (event){}才执行
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
try
{
#region
//最大接收包 4M
byte[] bufferReceive = new byte[1024 * 4];
WebSocketReceiveResult clientData = await webSocket.ReceiveAsync(new ArraySegment<byte>(bufferReceive), CancellationToken.None);
//接收Socket消息
if (clientData.MessageType == WebSocketMessageType.Text)
{
//解读收到的消息
byte[] buffer = new byte[clientData.Count];
Array.Copy(bufferReceive, 0, buffer, 0, buffer.Length);
string msgString = Encoding.UTF8.GetString(buffer);
MessageBase message = JsonConvert.DeserializeObject<MessageBase>(msgString);
message.Id = Guid.NewGuid().ToString();
message.Message = "我是回应啊";
//判断消息添加消息连接
if (keyValues.ContainsKey(message.Id))
{
keyValues[message.Id] = webSocket;
}
else
{
keyValues.Add(message.Id, webSocket);
}
//发送消息
if (webSocket != null && webSocket.State == WebSocketState.Open)
{
string jsonStr = JsonConvert.SerializeObject(message);
byte[] _byte = Encoding.UTF8.GetBytes(jsonStr);
webSocket.SendAsync(_byte, WebSocketMessageType.Text, true, CancellationToken.None);
}
//开启一个此消息的线程
//作用:一直等待接收前端发送过来的消息,直到接收到前端发送的关闭消息连接,此线程结束
await Handle(webSocket, message.Id, ip);
}
#endregion
}
catch (Exception ex)
{
//添加消息报错
//返给前端 关闭消息连接
ex.ToString();
MessageBase mb = new MessageBase
{
Id = "-1",
Type = MessageType.Closed,
Message = "closed"
};
string jsonStr = JsonConvert.SerializeObject(mb);
byte[] _byte = Encoding.UTF8.GetBytes(jsonStr);
await webSocket.SendAsync(_byte, WebSocketMessageType.Text, true, CancellationToken.None);
await context.Response.WriteAsync("closed");
}
}
else
{
await _next(context);
}
}
/// <summary>
/// 循环监控事件
/// </summary>
/// <param name="webSocket"></param>
/// <param name="uid"></param>
/// <param name="ip"></param>
/// <returns></returns>
private async Task Handle(WebSocket webSocket, string uid, string ip)
{
WebSocketReceiveResult clientData;
int id = 1;
do
{
//最大接收包 4M
byte[] bufferReceive = new byte[1024 * 4];
//在连接关闭之前 一直在这等待 前端给发消息 从而进行回复
clientData = await webSocket.ReceiveAsync(new ArraySegment<byte>(bufferReceive), CancellationToken.None);
if (clientData.CloseStatus != null && !clientData.CloseStatus.HasValue)
{//WebSocket连接关闭
break;
}
//接收Socket消息
if (clientData.MessageType == WebSocketMessageType.Text)
{
byte[] buffer = new byte[clientData.Count];
Array.Copy(bufferReceive, 0, buffer, 0, buffer.Length);
string msgString = Encoding.UTF8.GetString(buffer);
MessageBase message = JsonConvert.DeserializeObject<MessageBase>(msgString);
message.Id = uid;
message.Message = "我是回应" + id;
HandleMessage(message);
}
else if (clientData.MessageType == WebSocketMessageType.Binary)
{
byte[] allData = new byte[clientData.Count];
Array.Copy(bufferReceive, 0, allData, 0, allData.Length);
MessageBase message = new MessageBase()
{
Id = uid,
Type = MessageType.Monitor,
Message = new MemoryStream(allData)
};
HandleMessage(message);
}
} while (!clientData.CloseStatus.HasValue);
//WebSocket连接关闭,关闭接受消息并移除连接
WebsocketHandlerMiddleware.Remove(uid);
}
/// <summary>
/// 事件派发
/// </summary>
/// <param name="message"></param>
private void HandleMessage(MessageBase message)
{
if (!dic.ContainsKey(message.Type))
return;
foreach (MessageEvent messageEvent in dic[message.Type])
{
messageEvent(message);
}
}
/// <summary>
/// 删除连接
/// </summary>
/// <param name="Uid"></param>
/// <param name="stEnum"></param>
public static void Remove(string Uid)
{
if (keyValues.ContainsKey(Uid))
{
keyValues[Uid].Abort();
}
keyValues.Remove(Uid);
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message"></param>
public static void SendMsg(MessageBase message)
{
foreach (var item in keyValues)
{
string jsonStr = JsonConvert.SerializeObject(message);
byte[] _byte = Encoding.UTF8.GetBytes(jsonStr);
item.Value.SendAsync(_byte, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
}
三、在管道中配置WebSocket消息
四、在前端启动WebSocket
我这用的是vue3的代码结构
<script setup lang="ts">
let ws = new WebSocket("ws://localhost:8080");
//给后端发送消息 开启连接
ws.onopen = function (e) {
console.log("open:", e)
var date ={
Id : "111",
Type : 2,
Message : "开启连接"
}
console.log(ws)
ws.send(JSON.stringify(date));
};
//监听后端发送过来的消息
ws.onmessage = function (e) {
var date ={
Id : "222",
Type : 2,
Message : "消息"
}
console.log(e.data);
//处理消息,在页面展示内容(自由扩展)
ws.send(JSON.stringify(date));//发送消息给后台
};
//给后端发消息连接异常
ws.onerror = function (e) {
alert("网络连接错误!");
};
// 给后端发消息关闭连接
ws.onclose = function (e) {
alert("服务器断开!");
};
</script>
如下就是我webSocket连接成功,监听到的消息内容了,打印了一下
备注: 这是我在接口中调用的发送消息方法 给前端发消息,大家也可以参考一下
WebSocket 的使用方法不止于此,我这只是自己对他的了解进行了一下封装,大家可以参考一下!!!