Owin Websockets - 了解IOwinContext和WebSocketAccept

Pip*_*ine 7 .net c# sockets websocket owin

通过这里阅读并查看此处的示例:

我试图了解WebSocketAccept实际上做了什么.我知道WebSocketAccept是:

using WebSocketAccept =
    Action
    <
        IDictionary<string, object>, // WebSocket Accept parameters
        Func // WebSocketFunc callback
        <
            IDictionary<string, object>, // WebSocket environment
            Task // Complete
        >
    >;
Run Code Online (Sandbox Code Playgroud)

并以这种方式使用:

public void Configuration(IAppBuilder app)
    {
        app.Use(UpgradeToWebSockets);
        app.UseWelcomePage();
    }

    // Run once per request
    private Task UpgradeToWebSockets(IOwinContext context, Func<Task> next)
    {
        WebSocketAccept accept = context.Get<WebSocketAccept>("websocket.Accept");
        if (accept == null)
        {
            // Not a websocket request
            return next();
        }

        accept(null, WebSocketEcho);

        return Task.FromResult<object>(null);
    }
Run Code Online (Sandbox Code Playgroud)

那么accept()实际上是做什么的?它是否调用了WebSocketAccept的Func <>属性并定义了WebSocketEcho方法?WebSocketEcho定义为:

  private async Task WebSocketEcho(IDictionary<string, object> websocketContext)
Run Code Online (Sandbox Code Playgroud)

那websocketContext来自哪里?如果我们确定它是一个Web套接字请求,我们想要将其进一步传递到管道中,该怎么办?

小智 5

什么是 WebSocketAccept?

WebSocketAccept是一个正在使用的别名

例子:

...
using Foo.Bar
using MyBar = Fee.Bar
...
Run Code Online (Sandbox Code Playgroud)

在这里,我们使用来自 2 个不同命名空间的 Bar,但我们将第二个命名空间命名为 ' MyBar',以便我们可以区分两者。

为什么使用别名作为 WebSocketAccept?

在这种情况下,别名只是为了方便起见,这样您就不必键入整个名称,这意味着您可以使用别名来代替在使用时编写整个名称。

了解 WebSocketAccept

如果我们仔细观察,我们会发现类型是:

Action<A, B>
Run Code Online (Sandbox Code Playgroud)

这意味着它本质上是一个不返回并接受 2 个参数的函数,在 C# lambda 中:

(A, B) => { }
Run Code Online (Sandbox Code Playgroud)

我们看到第一个参数 (A) 是:IDictionary<string, object>,也称为 Owin 环境。

第二个参数是 (B) is:Func<C, D>这意味着它是一个接受 aC并返回 a 的函数D。在 C# lambda 中:

(C) => { return D; }
Run Code Online (Sandbox Code Playgroud)

然后我们需要深入研究第二个参数 (B) 的第一个参数 (C)。我们看到它需要一个 Owin 环境并返回一个Task.

什么是接受?

accept尝试从 中提取参数IOwinContext并将它们映射到WebSocketAccept类型。

如果它无法提取它们,null我们将继续处理下一个中间件。

否则,它是一个 websocket 请求,我们调用带有 2 个参数的函数 ( WebSocketAccept),正如我们上面讨论的 ( Action<A, B>)。

第一个参数是一个普通字典,其中包含websocket接受参数。

第二个参数是一个函数,它接受字典并返回任务。

该函数被其他人调用,代码的作用是将回调函数传递给调用者。

然后调用者使用正确的参数调用该函数。因为调用者知道函数的签名。该函数在接受 websocket 连接请求后调用。因此评论回调。

如果我们确定它是一个 Web 套接字请求后想要将其进一步传递到管道中该怎么办?

在示例中,回调函数WebSocketEcho本质上是您可以传入任何满足以下函数签名的函数:

Task MyCallbackFunction(IDictionary<string, object> context)
{
    // Do something
    return Task.FromResult(0);
}
Run Code Online (Sandbox Code Playgroud)

要点是您不调用该函数,该函数是为您调用的。您指定在协商 Web 套接字请求连接后,您决定发生什么。

WebSocketEcho函数为每个客户端调用一次,并循环直到客户端选择关闭连接。同时它会回显收到的任何内容。

免责声明:我也只是想了解网络套接字和owin,但我想为后代分享我的发现,因为没有人回答你的问题。我欢迎任何指正。

编辑
我在自己的实验中注意到,如果您从回调函数返回,则连接websocketContext将被Abort编辑。websocketContext这意味着如果您在结束回调后传递消息,则无法在连接上发送/接收消息。

更新
上次我尝试在 Windows 2008 R2 IIS 7.5 服务器上使用它时,我无法让 websocket 工作。然后根据此: https: //stackoverflow.com/a/14130152/1640121 - IIS 7.5服务器不支持websockets。
这意味着如果您的应用程序托管在 IIS 7.5 中,它将无法拥有 Websocket。

然后我想到了一个可能的解决方案:

  1. 使用单独的应用程序,例如处理 websocket 请求的服务程序(IIS 外部)。
  2. 使用反向代理将请求映射到服务应用程序

这对我来说太麻烦了,这让我暂时搁置了实现 websocket 的事情......