在asp.netcore(5.0)Web应用程序中,是否可以在没有无限while循环的情况下保持套接字活动?(while (webSocket.State == WebSocketState.Open
)如果循环是唯一的方法,这不是非常低效吗?
这基本上是我希望达到的目标
public class SocketController : Controller
{
[HttpGet]
[Route("Connect")]
public async Task ConnectAsync()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
SocketManager.registerSocket(User, webSocket);
var outputBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes("pong"));
await webSocket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
else
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
}
}
这似乎行得通,但似乎不对
public class SocketController : Controller
{
[HttpGet]
[Route("Connect")]
public async Task ConnectAsync()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
// stuff
while (webSocket.State == WebSocketState.Open) ;
}
else
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
}
}
检查套接字关闭的最小示例:
var socket = new WebSocket("wss://localhost:44331/Socket/Connect");
socket.onclose = function (err) {
console.log("CLOSED");
console.error(err);
};
如果我删除循环,连接在JS端关闭,当动作完成执行时,输出:
CLOSED
{
isTrusted: true,
bubbles: false,
cancelBubble: false,
cancelable: false,
code: 1006,
composed: false,
currentTarget: [WebSocket Object],
defaultPrevented: false,
eventPhase: 0,
path: [],
reason: "",
returnValue: true,
srcElement: [WebSocket Object],
target: [WebSocket Object],
timeStamp: 958.5999999998603,
type: "close",
wasClean: false
}
2条答案
按热度按时间uxh89sit1#
WebSocket使用ping/pong心跳来保持活动。
Ping帧可用作保活或用作验证远程端点仍在响应的手段。
但是,当客户端收到Ping时,必须向服务器发回Pong
当收到Ping帧时,端点必须发送Pong帧作为响应,除非它已经收到Close帧。它应该尽快用Pong帧响应。
您可以使用
KeepAliveInterval
来设置向客户端发送“ping”帧以确保代理保持连接打开的频率。默认值为两分钟。在您的代码中,
while (webSocket.State == WebSocketState.Open)
只是检查WebSocket的状态,它不会使websocket保持活动状态。当客户端由于连接丢失而断开连接时,不会自动通知服务器。只有当客户端发送断开连接消息时,服务器才会接收到该消息,如果Internet连接丢失,则无法接收该消息。如果您希望在发生这种情况时采取某些操作,请设置在特定时间窗口内未从客户端接收到任何消息后的超时。
dced5bon2#
即使晚了一点实际上,您的解决方案的问题在于,您的
while (webSocket.State == WebSocketState.Open);
执行CPU密集型轮询,应该避免。然而,我也感受到了同样的“问题”,这就是目前我的解决方案。不同的是,只有在循环块中接收到作为
await ws.ReceiveAsync
的东西时,才会处理循环。在Connect内部调用该方法,如下所示:
在我的例子中,我还添加了一个cancel-token,这样我就可以主动关闭连接。
如果有人有更好的解决方案,请随意纠正我:)