我想在 asp.net 核心中進行 WebSockets 聊天。我決定用中間件來做。然而,有一件事我一直在想一天 - 我不知道如何進行正確的廣播。問題是它不顯示其他用戶的訊息,而只是將您的訊息寫入用戶計數次數。
應該是這樣的(如果瀏覽器的 2 個選項卡中有 2 個用戶):
1:你好 2
2:你好 1
相反,我只看到 1 個用戶的 2 條相同訊息,而在瀏覽器的其他選項卡中,我什么也看不到。
這是中間件類:
public class WebSocketChatMiddleware
{
RequestDelegate _next;
ConcurrentDictionary<string, WebSocket> connections { get; set; }
public WebSocketChatMiddleware(RequestDelegate next)
{
_next = next;
connections = new ConcurrentDictionary<string, WebSocket>();
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await _next.Invoke(context);
return;
}
CancellationToken ct = context.RequestAborted;
WebSocket ws = await context.WebSockets.AcceptWebSocketAsync();
string wsID = Guid.NewGuid().ToString();
connections.TryAdd(wsID, ws);
while (true)
{
if (ct.IsCancellationRequested)
{
return;
}
string data = await ReadStringAsync(ws, ct);
if (string.IsNullOrEmpty(data))
{
if (ws.State != WebSocketState.Open)
{
break;
}
continue;
}
foreach (var item in connections) // not working broadcast
{
if (ws.State == WebSocketState.Open)
{
await SendStringAsync(ws, data, ct);
}
}
}
WebSocket dummy;
connections.TryRemove(wsID,out dummy);
await ws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure,"UserDisconnected",ct);
ws.Dispose();
await _next(context);
}
async Task<string> ReadStringAsync(WebSocket ws, CancellationToken ct = default)
{
var buffer = new ArraySegment<byte>(new byte[1024 * 8]);
using (MemoryStream ms = new MemoryStream())
{
WebSocketReceiveResult receiveResult;
do
{
ct.ThrowIfCancellationRequested();
receiveResult = await ws.ReceiveAsync(buffer, ct);
ms.Write(buffer.Array, buffer.Offset, receiveResult.Count);
} while (!receiveResult.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin); // Changing stream position to cover whole message
if (receiveResult.MessageType != WebSocketMessageType.Text)
return null;
using (StreamReader reader = new StreamReader(ms, System.Text.Encoding.UTF8))
{
return await reader.ReadToEndAsync(); // decoding message
}
}
}
Task SendStringAsync(WebSocket ws, string data, CancellationToken ct = default)
{
var buffer = System.Text.Encoding.UTF8.GetBytes(data);
var segment = new ArraySegment<byte>(buffer);
return ws.SendAsync(segment, WebSocketMessageType.Text, true, ct);
}
在 Startup.cs 中配置方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseWebSockets();
app.UseMiddleware<WebSocketChatMiddleware>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
我將非常感謝您的幫助 c:
uj5u.com熱心網友回復:
更改如下代碼:
foreach (var item in connections) // not working broadcast
{
//if (ws.State == WebSocketState.Open)
//{
// await SendStringAsync(ws, data, ct);
//}
if (item.Value.State != WebSocketState.Open)
{
continue;
}
await SendStringAsync(item.Value, data, ct);
}
結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/466832.html
上一篇:http錯誤413.1-.netCore中的請求物體太大
下一篇:.net核心中的條紋支付結賬
