0

2 部分问题

  1. 我是否正确实施了这个客户端?
  2. 如果我要实现自己的 WebSockets 服务器,我有什么要求允许 SignalR 的传输协商过程识别 WebSockets 并能够使用它进行通信?

请注意,我的技术限制目前涉及

  • Windows 7的,
  • 框架 4.5,
  • Owin 自托管(控制台)SignalR 服务器,
  • Owin 自托管(控制台).NET 客户端,
  • 网络客户端 (Javascript)

第 1 部分:尝试使用 System.Net.WebSockets.ClientWebSocket 客户端实现 Katana 示例

所以我正在构建一个自托管的 SignalR 进程,我在我的提琴手流量中注意到我的连接正在使用 LongPolling,而我希望它使用 WebSockets,所以我开始研究需要什么的过程使 WebSockets 可用。

一些快速研究导致混合信息:一些消息来源表明 WebSockets 仅在 Windows 8 和 IIS 8 上可用,并且 WebSockets 实现集成在操作系统级别。

一些消息来源指出,该限制仅适用于希望使用 HTTP.sys 的各方,并且自托管解决方案可以利用 WebSocket: Katana Sample WebSocket Server Katana Sample WebSocket Client

所以我着手实现 Katana 示例 - 我有一个 SignalR 服务器,我想通过 WebSockets、一个 .NET 客户端和一个 Web 客户端将它公开到我的 SignalR 服务器中,当我尝试在我的 . NET 客户端(截断当前不相关的客户端代码部分):

static void Main(string[] args)
        {
            Console.WriteLine("╔════════════════════════════════════════════════════════════════════════════╗");
            Console.WriteLine("╠»»»-                     Starting Service.Host-                   «««╣");

            Console.WriteLine("║-- Connecting to Client Messaging Hub-- ");
            Console.WriteLine("║.....Attempting to upgrade to WebSockets ");

            //UseDefaultConnectionParameters();
            Connect("ws://localhost:8080");

            Console.WriteLine(String.Format("║-->Connection Established [{0}]", @"ws://localhost:8080"));
            Console.WriteLine("╠»»»                   Service.Host now  started                   «««╣");
            Console.WriteLine("╚════════════════════════════════════════════════════════════════════════════╝");
            Console.ReadLine();

        }
        private static async Task Connect(string uri)
        {
            ClientWebSocket websocket = null;
            try
            {
                websocket = new ClientWebSocket();//<= Throws exception
                await websocket.ConnectAsync(new Uri(uri), CancellationToken.None);
                await Task.WhenAll(Receive(websocket), Send(websocket));
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception: {0}", ex);
            }
            finally
            {
                if (websocket != null)
                    websocket.Dispose();
                Console.WriteLine();

                lock(master)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("WebSocket closed.");
                    Console.ResetColor();
                }
            }


        }

我的 Connect() 函数中的行

ClientWebSocket websocket = new System.Net.WebSockets.ClientWebSocket();

投掷

Exception: System.PlatformNotSupportedException: The WebSocket protocol is not s
upported on this platform.
   at System.Net.WebSockets.ClientWebSocket..ctor().  

(我的 CLR 客户端库面向 .NET Framework 4.5)

这是否遇到了硬限制,您无法在没有 Windows 8 的情况下从 System.Net.WebSockets 命名空间创建 WebSocket 客户端?

第 2 部分:调查第三方 WebSocket 服务器/客户端的影响

假设第 1 部分中的代码是死胡同,我想我的下一个可行选择是使用适当的客户端(例如 SignalR.Client.WebSocket4Net )实现第三方 Web 套接字服务器(例如SuperWebSocket)并公开套接字服务器供 SignalR 使用。我希望答案是“什么都没有。它会正常工作”但是一旦我站起来 SuperWebSocket 并扩展我的 CLR 客户端以实现 SignalR.Client.WebSocket4Net,SignalR 通信需要什么来协商升级请求并开始传输在 ws:// ?


任何人都可以在这两条路径中的任何一条上提供任何指导吗?如果我选择了错误的路线,我预见到会浪费很多时间。

4

1 回答 1

0

第1部分

在 Windows 8 和 2012 中发布的新版本 http.sys 负责将常规 HTTP 请求转换为持久的、二进制的、双向的 TCP 连接,即 WebSocket。这就是允许 IIS 在建立 websocket 连接时切换协议的原因。

为什么 ClientWebSockets 在 Windows 7 上不起作用?好吧,这根本没有意义,但服务器和客户端之间可能存在一些共享功能,这就是为什么它在带有PlatformNotSupportedException.

第2部分

您可能需要实现自己的ITransport来创建自己的WebSocketTransport,并将其注册到TransportManager中。这纯粹是猜测,我从未尝试过这样做:) 只是,请注意您可以找到的关于此的少量文档或经验...

但是问题来了,如果您的客户端切换到另一个传输,它将失败!因为由于操作系统无法在同一个端口上侦听长轮询和 websocket,所以对 WebSocket 组件的常规 HTTP 请求将不会产生任何影响。这就是 http.sys 在其新版本中所做的技巧,侦听 HTTP 常规请求,如果需要,仍然可以在 websocket 上打开其中一个请求。

我的 0.02

为什么选择 SignalR?这是一个不会很快被需要的 polyfill。WebSockets 是一种标准的、广泛支持的技术,并且很容易在旧浏览器中使用websocket-js进行 polyfill 。SignalR仅适用于广播一般数据的应用程序(检查限制部分)。我编写并维护了一个名为 WebSocketListener 的 WebSocket 库,您可能想尝试一下 :)(虽然它没有客户端)。我建议您在选择一个库之前测试几个库的性能和可扩展性;)

于 2014-10-31T22:34:34.260 回答