WebSocket服務搭建

绯颜旧雨發表於2024-05-27

1、在NuGet包管理工具安裝websocket包

2、新增自定義中介軟體

app.UseWebSockets();
app.UseMiddleware<CustomWebSocketMiddleware>();

3、編寫websocket中介軟體

private readonly RequestDelegate _next;
private ILogger<CustomWebSocketMiddleware> _Logger;
public List<WebSocketConnect> _connections = new List<WebSocketConnect>();
public CustomWebSocketMiddleware(RequestDelegate next, ILogger<CustomWebSocketMiddleware> logger)
{
_next = next;
_Logger = logger;
}

public async Task InvokeAsync(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await _next(context); // 如果不是WebSocket請求,則繼續處理管道中的下一個中介軟體
return;
}
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();

// 啟動WebSocket連線處理任務
await ProcessWebSocketAsync(context, webSocket);
}

private async Task ProcessWebSocketAsync(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4]; // 4KB buffer
WebSocketReceiveResult result;
var ipProt = context.Request.Host.Value.Split(":");
WebSocketConnect connect = new WebSocketConnect
{
Socket = webSocket,
path = context.Request.Path.Value,
ip = ipProt[0],
port = ipProt[1]
};
_Logger.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}寫入wobsocket連線,{ipProt[0]} {ipProt[1]}{ context.Request.Path.Value}");
//判斷連線池是否存在該連結
if (!_connections.Any(connection => connection.path == context.Request.Path.Value && connection.Socket.State== WebSocketState.Open))
{
for (var i=0;i<_connections.Count;i++)
{
if (_connections[i].path==context.Request.Path && (_connections[i].Socket.State==WebSocketState.Closed || _connections[i].Socket.State == WebSocketState.Aborted))
{
_connections.Remove(_connections[i]);
}
}
_connections.Add(connect);
}
try
{
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
if (result.MessageType == WebSocketMessageType.Text)
{
string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);
Console.WriteLine($"Received: {receivedMessage}");

// 傳送訊息回顯
//string echoMessage = $"Echo: {receivedMessage}";
await ProcessReceive(receivedMessage, webSocket, context);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
catch (Exception ex)
{
_Logger.LogError(ex.Message);
if (webSocket.State == WebSocketState.Open)
{
_connections.Remove(connect);
await webSocket.CloseAsync(WebSocketCloseStatus.InternalServerError, "連線異常", CancellationToken.None);
}
}
}

private async Task ProcessReceive(string message, WebSocket webSocket, HttpContext context)
{

//處理訊息

}


4、在前端呼叫websocket服務

const ws = ref(null)
const reconnection = () => {
  ws.value = new WebSocket(env.socket.baseUrl)
  ws.value.addEventListener('open', () => {
    socketState.value = '連線成功'
    console.log('連線成功')
  })
  ws.value.addEventListener('message', (event) => {
    
  })
  ws.value.addEventListener('close', (e) => {
    socketState.value = '連線已關閉'
    console.log('WebSocket連線已關閉')
  })
  ws.value.addEventListener('error', (error) => {
    socketState.value = '連線錯誤,已斷開連線'
    console.error('WebSocket發生錯誤:', error)
  })
}

傳送訊息

ws.value.send(JSON.stringify(data))
 

相關文章