在NetCore框架中实现WebSocket即时通讯功能,不需要依赖复杂的第三方组件,原生就提供了完善的WebSocket支持,也可以结合SignalR简化开发流程。下面我们通过一个基础的即时通讯实例,演示完整的实现方式。

基础环境准备
首先我们需要创建一个NetCore Web应用项目,这里以NetCore 6及以上版本为例,创建完成后不需要额外安装特殊依赖,原生库已经包含WebSocket相关的实现类。
服务端实现
原生WebSocket方式实现
首先需要在Program.cs中启用WebSocket中间件,代码如下:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// 启用WebSocket中间件
app.UseWebSockets();
// 处理WebSocket请求
app.Map("/ws", async (HttpContext context) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
// 接受WebSocket连接
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
await HandleWebSocketAsync(webSocket);
}
else
{
context.Response.StatusCode = 400;
}
});
// WebSocket连接处理逻辑
static async Task HandleWebSocketAsync(System.Net.WebSockets.WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
// 持续接收客户端消息
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
// 将接收到的消息回传给客户端
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
// 继续接收下一条消息
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
// 关闭连接
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
app.Run();
使用SignalR简化开发
如果需要更复杂的功能比如连接分组、自动重连等,可以使用SignalR,首先需要安装Microsoft.AspNetCore.SignalR包,然后创建Hub类:
using Microsoft.AspNetCore.SignalR;
// 定义即时通讯Hub
public class ChatHub : Hub
{
// 客户端调用的方法,发送消息给所有连接的客户端
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message, DateTime.Now);
}
}
接着在Program.cs中注册SignalR服务并映射Hub端点:
var builder = WebApplication.CreateBuilder(args);
// 注册SignalR服务
builder.Services.AddSignalR();
var app = builder.Build();
// 映射Hub端点
app.MapHub<ChatHub>("/chatHub");
app.Run();
客户端实现
原生WebSocket客户端
我们可以使用简单的HTML页面作为客户端,通过JavaScript的原生WebSocket API连接服务端:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSocket客户端</title>
</head>
<body>
<input type="text" id="messageInput" placeholder="输入消息" />
<button onclick="sendMessage()">发送</button>
<div id="messages"></div>
<script>
// 连接服务端的WebSocket端点
const ws = new WebSocket("ws://localhost:5000/ws");
// 连接建立成功回调
ws.onopen = function() {
console.log("WebSocket连接已建立");
};
// 接收服务端消息回调
ws.onmessage = function(event) {
const messagesDiv = document.getElementById("messages");
messagesDiv.innerHTML += "<p>收到消息: " + event.data + "</p>";
};
// 发送消息方法
function sendMessage() {
const input = document.getElementById("messageInput");
const message = input.value;
if (message) {
ws.send(message);
input.value = "";
}
}
</script>
</body>
</html>
SignalR客户端
如果是SignalR方式,客户端需要先引入SignalR的JS库,然后实现连接和消息收发:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>SignalR即时通讯客户端</title>
<!-- 引入SignalR库 -->
<script src="https://ipipp.com/signalr/signalr.min.js"></script>
</head>
<body>
<input type="text" id="userInput" placeholder="用户名" />
<input type="text" id="messageInput" placeholder="输入消息" />
<button onclick="sendMessage()">发送</button>
<div id="messages"></div>
<script>
// 创建SignalR连接
const connection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:5000/chatHub")
.build();
// 接收服务端推送的消息
connection.on("ReceiveMessage", (user, message, time) => {
const messagesDiv = document.getElementById("messages");
messagesDiv.innerHTML += `<p>${time} ${user}: ${message}</p>`;
});
// 启动连接
connection.start().catch(err => console.error(err));
// 发送消息方法
function sendMessage() {
const user = document.getElementById("userInput").value;
const message = document.getElementById("messageInput").value;
if (user && message) {
// 调用服务端的SendMessage方法
connection.invoke("SendMessage", user, message).catch(err => console.error(err));
document.getElementById("messageInput").value = "";
}
}
</script>
</body>
</html>
常见问题处理
在实际开发中,我们还需要处理一些常见问题:
- 连接管理:原生WebSocket方式需要手动维护在线连接列表,SignalR会自动管理连接,也可以通过
Context.ConnectionId获取每个连接的唯一标识。 - 断线重连:SignalR客户端内置了自动重连机制,可以通过
withAutomaticReconnect()配置重连策略,原生WebSocket需要手动监听onclose事件实现重连。 - 消息格式:建议使用JSON格式传输消息,方便扩展字段,避免直接传输字符串导致格式混乱。
总结
通过上面的实例可以看到,NetCore下实现WebSocket即时通讯既可以选择原生方式灵活控制,也可以借助SignalR减少重复开发工作。开发者可以根据项目需求选择合适的实现方式,原生方式适合轻量、自定义需求高的场景,SignalR适合需要分组、自动重连等复杂功能的场景。