下面是我给您详细讲解“C#使用WebSocket实现聊天室功能”的完整攻略。
什么是WebSocket
WebSocket 是一种网络通信协议,能够在单个 TCP 连接上进行全双工通信。它在客户端和服务器之间建立一个套接字连接,使得数据可以双向传输。
实现聊天室功能的方案
要使用WebSocket实现聊天室功能,需要一个WebSocket的服务器来处理客户端请求和消息的转发。而在C#中,我们可以使用ASP.NET WebSocket库来创建 WebSocket 服务器。
前端实现
在前端页面中,需要使用WebSocket对象建立与服务器的连接,并在连接成功后通过send()方法向服务器发送消息。
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
console.log('连接成功');
};
ws.onmessage = function (evt) {
console.log('收到来自服务器的消息:', evt.data);
};
ws.onerror = function (evt) {
console.log('连接发生错误:', evt);
};
ws.onclose = function (evt) {
console.log('连接关闭');
};
function sendMessage() {
var message = document.getElementById("messageInput").value;
ws.send(message);
}
服务端实现
在服务端,我们可以使用ASP.NET WebSocket库来实现 WebSocket 服务器。代码如下:
using System;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
namespace ChatServer
{
public class WebSocketHandler
{
private readonly WebSocket _webSocket;
public WebSocketHandler(WebSocket webSocket)
{
_webSocket = webSocket;
}
public async Task Handle()
{
var buffer = new byte[1024 * 4];
while (_webSocket.State == WebSocketState.Open)
{
var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Text)
{
// 将接收到的消息发送给所有客户端
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
await SendMessageToAllAsync(message);
}
else if (result.MessageType == WebSocketMessageType.Close)
{
// 客户端关闭连接时,需要将其移除
await RemoveWebSocketAsync(_webSocket);
break;
}
}
}
}
public class ChatWebSocketMiddleware
{
private readonly RequestDelegate _next;
private readonly ConcurrentDictionary<string, WebSocket> _webSockets;
public ChatWebSocketMiddleware(RequestDelegate next)
{
_next = next;
_webSockets = new ConcurrentDictionary<string, WebSocket>();
}
public async Task Invoke(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await _next.Invoke(context);
return;
}
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
_webSockets.TryAdd(webSocket.GetHashCode().ToString(), webSocket);
var handler = new WebSocketHandler(webSocket);
await handler.Handle();
await RemoveWebSocketAsync(webSocket);
}
private Task SendMessageToAllAsync(string message)
{
var tasks = new List<Task>();
foreach (var webSocket in _webSockets)
{
if (webSocket.Value.State == WebSocketState.Open)
{
var encodedMessage = Encoding.UTF8.GetBytes(message);
var buffer = new ArraySegment<byte>(encodedMessage, 0, encodedMessage.Length);
tasks.Add(webSocket.Value.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None));
}
}
return Task.WhenAll(tasks);
}
private Task RemoveWebSocketAsync(WebSocket webSocket)
{
_webSockets.TryRemove(webSocket.GetHashCode().ToString(), out _);
return Task.CompletedTask;
}
}
public static class ChatWebSocketExtensions
{
public static IApplicationBuilder UseChatWebSocketMiddleware(this IApplicationBuilder app)
{
return app.UseMiddleware<ChatWebSocketMiddleware>();
}
}
}
在上述代码中,我们创建了一个 WebSocketHandler 类来处理每个连接的数据收发,使用 ConcurrentDictionary
然后创建 ChatWebSocketMiddleware 类来处理每个 WebSocket 请求,验证请求是否为有效的 WebSocket 连接,并将其添加到活动连接列表中。接着就可以在 Handle() 方法中接收和发送消息。
最后,创建 ChatWebSocketExtensions 类,以便在 Startup.cs 中使用该中间件。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// …
app.UseChatWebSocketMiddleware();
// …
}
至此,我们就成功实现了一个简单的聊天室功能。
示例说明
示例一
我们可以创建一个简单的 HTML 页面来测试我们的聊天室功能。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebSocket Chat Demo</title>
</head>
<body>
<div id="messages"></div>
<input id="messageInput" type="text" />
<button onclick="sendMessage()">发送</button>
<script>
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
console.log('连接成功');
};
ws.onmessage = function (evt) {
console.log('收到来自服务器的消息:', evt.data);
var div = document.createElement('div');
div.innerHTML = evt.data;
document.getElementById('messages').appendChild(div);
};
ws.onerror = function (evt) {
console.log('连接发生错误:', evt);
};
ws.onclose = function (evt) {
console.log('连接关闭');
};
function sendMessage() {
var message = document.getElementById("messageInput").value;
ws.send(message);
document.getElementById("messageInput").value = "";
}
</script>
</body>
</html>
启动后台 C# 应用程序,然后在浏览器中打开该 HTML 页面,你会发现页面会显示所有发送到聊天室的消息,并可以通过文本框发送消息。
示例二
我们在 ASP.NET CORE 的中间件中添加 WebSocket 支持,从而实现了 WebSocket 服务器。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddWebSocketManager();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseWebSockets();
app.MapWebSocketManager("/chat", app.ApplicationServices.GetService<ChatRoomHandler>());
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
public class ChatRoomHandler : WebSocketHandler
{
public ChatRoomHandler(WebSocketConnectionManager webSocketConnectionManager) : base(webSocketConnectionManager)
{
}
public override Task OnConnected(WebSocket socket)
{
return base.OnConnected(socket);
}
public override Task ReceiveAsync(WebSocket socket, WebSocketReceiveResult result, byte[] buffer)
{
string message = $"{socket.GetHashCode().ToString()} said: {Encoding.UTF8.GetString(buffer, 0, result.Count)}";
return SendMessageToAllAsync(message);
}
}
public static class WebSocketExtensions
{
public static IServiceCollection AddWebSocketManager(this IServiceCollection services)
{
services.AddSingleton<WebSocketConnectionManager>();
return services;
}
public static IApplicationBuilder MapWebSocketManager(this IApplicationBuilder app, string path, Type type)
{
return app.Map(path, builder =>
{
builder.UseMiddleware<WebSocketManagerMiddleware>(type);
});
}
}
public class WebSocketManagerMiddleware
{
private readonly RequestDelegate _next;
private readonly WebSocketHandler _webSocketHandler;
public WebSocketManagerMiddleware(RequestDelegate next, WebSocketHandler webSocketHandler)
{
_next = next;
_webSocketHandler = webSocketHandler;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await _next(context);
return;
}
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await _webSocketHandler.OnConnected(webSocket);
try
{
await _webSocketHandler.ReceiveAsync(webSocket);
}
catch (Exception ex)
{
await _webSocketHandler.OnDisconnected(webSocket);
}
}
}
该示例演示了如何创建 WebSocket 基础结构以处理 WebSocket 连接。WebSocketConnectionManager 类负责管理所有 WebSocket 的集合,其中包含 WebSocket 对象和 ID。WebSocketHandler 类负责处理 WebSocket 连接上的事件,包括消息收发、连接和断开连接。
反复测试后可发现,我们已经成功实现了聊天室的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#使用WebSocket实现聊天室功能 - Python技术站