使用 HTTP 实现近实时通信的技术有很多,如轮询、长轮询、服务器发送事件,甚至 Webhooks。
所有方法都有一个共同的问题:它们仅限于单向通信。
在本文中,我们将探讨 WebSocket(一种构建在 TCP/IP 协议之上的协议,允许双向实时通信),并用它在 .NET 8 中实现一个简单的聊天应用程序。
WebSocket 与服务器发送事件(SSE)
与之前的文章一样,我将把 WebSocket 与最接近的替代品 SSE 进行比较。
相似之处
SSE 和 WebSockets:
- 使用单个持久的 TCP/IP 连接
- 所有现代浏览器都支持
- 允许实时通信
不同点
服务器发送事件使用简单的 HTTP 请求,受限于其请求-响应设计,只能进行单向通信。
WebSocket 是一种建立在 TCP/IP 基础上的双向(全双工)实时通信协议。它使用 HTTP 请求建立连接(握手),然后升级为 WebSocket 连接。
与 SSE 不同,WebSocket 还支持二进制信息。
这使它成为需要双向通信(如聊天应用程序)的绝佳选择。
实现 WebSocket 服务器
让我们在 .NET 8 中构建一个简单的 WebSocket 服务器。
首先,我们将设置一个 Web 服务器和所需的依赖项。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ChatService>();
var app = builder.Build();
app.UseWebSockets();
然后,我们添加一个简单的端点,它将检查所需的标头信息,以确定它是否是一个 WebSocket 请求,如果是,则接受它并将其传递给我们的ChatService。
app.MapGet("/", async (HttpContext context, ChatService chatService) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
var webSocket = wait context.WebSockets.AcceptWebSocketAsync();
wait chatService.HandleWebSocketConnection(webSocket);
}
else
{
context.Response.StatusCode = 400;
wait context.Response.WriteAsync("预期有 WebSocket 请求");
}
});
在 ChatService 中,我们将处理 WebSocket 连接。它是一个单例服务,可以跟踪所有连接的客户端。
public class ChatService
{
private readonly List<WebSocket> _sockets = new();
public async Task HandleWebSocketConnection(WebSocket socket)
{
_sockets.Add(socket);
var buffer = new byte[1024 * 2];
while (socket.State == WebSocketState.Open)
{
var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), default);
if (result.MessageType == WebSocketMessageType.Close)
{
await socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, default);
break;
}
foreach (var s in _sockets)
{
await s.SendAsync(buffer[..result.Count], WebSocketMessageType.Text, true, default);
}
}
_sockets.Remove(socket);
}
}
当 WebSocket 打开时,我们等待下一条消息。如果是 Close 消息,只需关闭连接即可。如果没有,我们读取它并将其写入分配的缓冲区。
然后,我们从包含该消息的缓冲区中取出一个片段,发送给所有已连接的客户端。
为了保持简单,我们不会验证消息类型或消息大小,也不会序列化/反序列化为域实体,而这可能是您在实际应用中需要做的事情。
实现 WebSocket 客户端
由于所有浏览器都支持 WebSocket,因此我们将使用 HTML 和 JavaScript 构建客户端。
<div id="messages"></div>
<input id="chatbox" >
<script>
const socket = new WebSocket('ws://localhost:5007');
socket.onmessage = function (event) {
const messages = document.getElementById("messages");
messages.innerHTML += `<p>${event.data}</p>`;
};
document.getElementById("chatbox").addEventListener("keyup", function(event) {
if (event.key === "Enter") {
socket.send(event.target.value);
event.target.value = "";
}
});
</script>
这段简单的代码会打开一个 WebSocket 连接,并显示类似聊天应用程序的内容。
更多用例,请查看GitHub。
作者: Roko Kovač
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/im/38702.html