【问题标题】:Owin Websockets - Understanding IOwinContext and WebSocketAcceptOwin Websockets - 了解 IOwinContext 和 WebSocketAccept
【发布时间】:2015-06-15 02:38:21
【问题描述】:

通读here并查看示例here

我试图了解 WebSocketAccept 的实际作用。我知道 WebSocketAccept 是:

using WebSocketAccept =
    Action
    <
        IDictionary<string, object>, // WebSocket Accept parameters
        Func // WebSocketFunc callback
        <
            IDictionary<string, object>, // WebSocket environment
            Task // Complete
        >
    >;

并以这种方式使用:

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);
    }

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

  private async Task WebSocketEcho(IDictionary<string, object> websocketContext)

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

【问题讨论】:

    标签: c# .net sockets websocket owin


    【解决方案1】:

    什么是 WebSocketAccept?

    WebSocketAcceptusing alias

    例子:

    ...
    using Foo.Bar
    using MyBar = Fee.Bar
    ...
    

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

    为什么使用别名作为 WebSocketAccept?

    这种情况下的别名只是为了方便,这样你就不必输入整个东西,这意味着在使用它的时候不用写整个名字,你可以使用别名来代替。

    了解 WebSocketAccept

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

    Action<A, B>
    

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

    (A, B) => { }
    

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

    第二个参数是 (B) 是:Func&lt;C, D&gt;,这意味着它是一个接受 C 并返回 D 的函数。在 C# 中:

    (C) => { return D; }
    

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

    什么是接受?

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

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

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

    第一个参数是一个普通的字典,里面包含了websocket的接受参数。

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

    这个函数被其他人调用,代码所做的就是将回调函数传递给调用者。

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

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

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

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

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

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

    免责声明:我也只是想围绕网络套接字和 owin 进行研究,但我想为后代分享我的发现,因为没有人回答您的问题。我欢迎任何更正。

    编辑
    我在自己的实验中注意到,如果您从回调函数返回,websocketContext 连接将是Aborted。这意味着如果您在结束回调后传递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...

    【讨论】:

    • 我在尝试相同的代码时收到 400 Bad Request。
    猜你喜欢
    • 2012-05-25
    • 1970-01-01
    • 2014-06-23
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多