通过封闭的websocket连接发送数据时阻止应用程序崩溃

时间:2016-12-15 01:03:34

标签: c# websocket asp.net-core asp.net-core-1.0

ASP.NET Core应用程序在客户端使用websocket连接,在服务器端使用Microsoft.AspNetCore.WebSockets.Server 0.1.0(nuget上的最新稳定版本)。简单的发送代码是

await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk); 

问题是这条线在关闭连接时抛出错误。如果进程成功,我希望该方法返回一个布尔值。我已经检查连接是否打开如下:

_ws.State == WebSocketState.Open 

但如果用户有此功能,则无效 拔掉网线或断开设备(几乎所有情况除了关闭浏览器)。

作为一个额外的,我不知道如何模拟两个客户端之一的网络连接丢失和我认为WebSocketState是只读的,请警告我,如果我错了我不认为更短的ping会解决这个问题。 我有两个想法:

  1. 我可以在try catch块中使用发件人代码。 (我对在生产代码中使用try catch感到不舒服)

  2. 我可以在客户端设置间隔,并向服务器询问“对我来说什么是新的”。我觉得这很糟糕,因为它远不是一个websocket(更接近http)。

  3. 有没有办法解决这个问题而不使用try catch?我知道这不是一个合格的问题,但对我来说是一个合格的问题。如果需要,我可以分享完整的代码。

    更新1

    使用服务器端日志记录后


    虽然消息在生产环境中运行良好,但我通过拔下网络电缆并将数据发送到客户端来断开客户端连接。我使用try catch而没有捕获。然后我得到 this 错误。
    这意味着我无法通过使用try catch来检测丢失的连接。我想我可以通过处理这个投掷来解决这个问题。
    如何处理此错误?

    UPDATE2

    我注意到“由于c#6 link ,因此”异常无效方法的异常无法捕获“和”可以在catch中使用等待“但是我可以如果我不能以这种方式解决问题,我可以尝试同步await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk).runsynchronously();

    UPDATE3

    同步运行没有帮助。使用try catch没有区别。结果提问,asp.net核心websocket如何ping?

    UPDATE4

    使用Microsoft.aspnetcore.websockets.server 0.1.0时的日志文件

    fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HL1940BSEV8O": An unhandled exception was thrown by the application. System.IO.IOException: Unexpected end of stream at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.<EnsureDataAvailableOrReadAsync>d__38.MoveNext()
    使用Microsoft.aspnetcore.websockets 1.0.0时的日志文件 fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HL19H5R4CS21": An unhandled exception was thrown by the application. System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.IO.IOException: Error -4077 ECONNRESET connection reset by peer ---> Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4077 ECONNRESET connection reset by peer

2 个答案:

答案 0 :(得分:6)

我可能会遗漏某些内容,但为什么无法以下列方式将发送操作包装在返回bool的方法中:

private async Task<bool> DoSend()
{
    bool success = true;

    try
    {
        await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk);
    }
    catch (Exception ex)
    {
        // Do some logging with ex
        success = false;
    }

    return success;
}

我还建议阅读有关Async All The Way的内容,它应该清除async voidasync Taskasync Task<T>

的一些混淆

答案 1 :(得分:0)

在C#6.0中捕获异步方法的异常之前,您应该使用ExceptionDispatchInfo类型。然后代码将如下所示:

private async Task<bool> DoSend()
{
    bool success = true;
    ExceptionDispatchInfo capturedException = null;

    try
    {
        await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk);
    }
    catch (Exception ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }

    if (capturedException != null)
    {
        await ExceptionHandler();

        if (needsThrow)
        {
            capturedException.Throw();
        }
    }

    success = capturedException == null;

    return success;
}