在C#中实现WebSocket实时双向通信,既可以基于原生WebSocket类开发,也可以借助成熟的SignalR框架简化开发流程,两种方式都能实现服务端和前端的实时数据交互,下面分别介绍具体实现方法。

C#原生WebSocket服务端实现
创建控制台服务端项目
首先新建一个C#控制台应用,引入System.Net.WebSockets命名空间,该命名空间提供了原生WebSocket的实现类,无需额外安装第三方包。
核心服务端代码如下,实现接收客户端消息并回传的功能:
using System;
using System.Net;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WebSocketServer
{
class Program
{
static async Task Main(string[] args)
{
// 创建HTTP监听器,WebSocket基于HTTP握手建立连接
HttpListener listener = new HttpListener();
// 监听本地8080端口的ws请求
listener.Prefixes.Add("http://localhost:8080/ws/");
listener.Start();
Console.WriteLine("WebSocket服务端已启动,监听地址:http://localhost:8080/ws/");
while (true)
{
// 等待客户端连接请求
HttpListenerContext context = await listener.GetContextAsync();
// 判断是否为WebSocket请求
if (context.Request.IsWebSocketRequest)
{
// 处理WebSocket连接
ProcessWebSocketAsync(context);
}
else
{
context.Response.StatusCode = 400;
context.Response.Close();
}
}
}
static async Task ProcessWebSocketAsync(HttpListenerContext context)
{
WebSocketContext wsContext = await context.AcceptWebSocketAsync(null);
WebSocket webSocket = wsContext.WebSocket;
Console.WriteLine("客户端已连接");
byte[] buffer = new byte[1024];
try
{
while (webSocket.State == WebSocketState.Open)
{
// 接收客户端消息
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
string clientMsg = Encoding.UTF8.GetString(buffer, 0, result.Count);
Console.WriteLine($"收到客户端消息:{clientMsg}");
// 构造回传消息
string responseMsg = $"服务端已收到消息:{clientMsg}";
byte[] responseBuffer = Encoding.UTF8.GetBytes(responseMsg);
// 向客户端发送消息
await webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
catch (Exception ex)
{
Console.WriteLine($"通信异常:{ex.Message}");
}
finally
{
if (webSocket.State != WebSocketState.Closed)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "连接关闭", CancellationToken.None);
}
Console.WriteLine("客户端已断开连接");
}
}
}
}
服务端代码说明
上述代码首先通过HttpListener监听指定端口的HTTP请求,当收到WebSocket握手请求时,调用AcceptWebSocketAsync方法完成握手,建立WebSocket连接。之后通过循环接收客户端发送的消息,处理后再回传给客户端,当连接关闭时释放相关资源。
前端WebSocket客户端实现
前端使用原生JavaScript的WebSocket API即可与服务端建立连接,无需引入额外库,代码如下:
// 创建WebSocket连接,地址与服务端监听地址对应
const ws = new WebSocket('ws://localhost:8080/ws/');
// 连接建立成功回调
ws.onopen = function() {
console.log('WebSocket连接已建立');
// 连接成功后发送一条测试消息
ws.send('Hello WebSocket Server');
};
// 接收服务端消息回调
ws.onmessage = function(event) {
console.log('收到服务端消息:', event.data);
};
// 连接关闭回调
ws.onclose = function() {
console.log('WebSocket连接已关闭');
};
// 通信错误回调
ws.onerror = function(error) {
console.error('WebSocket通信错误:', error);
};
// 页面添加发送消息的方法,可绑定到按钮点击事件
function sendMessage() {
const input = document.getElementById('msgInput');
const msg = input.value;
if (msg && ws.readyState === WebSocket.OPEN) {
ws.send(msg);
input.value = '';
}
}
前端的HTML页面只需要添加一个输入框和发送按钮即可配合上述JS代码使用,示例HTML结构如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>WebSocket客户端</title>
</head>
<body>
<div>
<input type="text" id="msgInput" placeholder="输入要发送的消息">
<button onclick="sendMessage()">发送消息</button>
</div>
<div id="msgList"></div>
<script src="client.js"></script>
</body>
</html>
使用SignalR简化开发
如果项目基于ASP.NET Core开发,使用SignalR框架可以更高效地实现WebSocket通信,无需手动处理握手、消息分片等底层逻辑,首先安装Microsoft.AspNetCore.SignalR包。
SignalR服务端实现
创建Hub类作为通信的核心:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace SignalRServer
{
public class ChatHub : Hub
{
// 客户端可调用的方法,用于发送消息
public async Task SendMessage(string user, string message)
{
// 将消息广播给所有连接的客户端
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
在Startup或Program类中配置SignalR服务:
var builder = WebApplication.CreateBuilder(args);
// 添加SignalR服务
builder.Services.AddSignalR();
var app = builder.Build();
// 映射Hub路由
app.MapHub<ChatHub>("/chatHub");
app.Run();
SignalR前端实现
前端需要引入SignalR的JS客户端库,然后通过以下代码建立连接:
// 创建SignalR连接
const connection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:5000/chatHub")
.build();
// 接收服务端广播的消息
connection.on("ReceiveMessage", (user, message) => {
console.log(`${user}说:${message}`);
});
// 启动连接
connection.start().then(() => {
console.log("SignalR连接已建立");
});
// 发送消息的方法
function sendMsg() {
const user = document.getElementById("userInput").value;
const msg = document.getElementById("msgInput").value;
// 调用服务端的SendMessage方法
connection.invoke("SendMessage", user, msg).catch(err => console.error(err));
}
开发注意事项
- 原生WebSocket开发时需要注意消息的分片处理,长消息可能会被拆分成多个帧传输,需要拼接完整后再处理。
- 生产环境建议为WebSocket服务配置SSL证书,使用wss协议传输数据,避免数据被窃听。
- 需要做好连接的心跳检测,避免无效连接占用服务端资源,SignalR已经内置了心跳机制,原生开发需要手动实现。
- 前端连接断开后可以实现自动重连逻辑,提升用户体验。