【问题标题】:Dart upgrade client Socket to WebSocketDart 将客户端 Socket 升级为 WebSocket
【发布时间】:2018-12-11 10:08:21
【问题描述】:

由于 Dart 中的WebSocket 不允许直接设置SecurityContext(我需要进行证书检查),我想与SecureSocket 实例建立连接,然后使用 WebSocket.fromUpgradedSocket 构造函数从中创建一个 WebSocket 实例。

这个想法最初是由here提出的。

但是,我无法让它与以下代码一起使用(虽然我想要 wss,但甚至 ws 都不起作用):

sock = await Socket.connect('ws://echo.websocket.org', 80);
socket = WebSocket.fromUpgradedSocket(sock, serverSide: false);
socket.listen(myListener);
// Send some dummy data
var list = utf8.encode("hello");
var data = list is Uint8List ? list : Uint8List.fromList(list);
socket.add(data);

这里 sock 是 Socket 类型,socket 是 WebSocket 类型,而 myListener 是一个在收到消息时打印一些调试语句的函数。我没有收到错误,但我也没有进入侦听器 - 当我用这一行替换前两行时我会这样做:

socket = await WebSocket.connect('ws://echo.websocket.org');    

我认为问题在于我的 Socket 'sock' 没有升级,而上述构造函数的 WebSocket source code 明确指出:'从已升级的套接字创建 WebSocket。'。

所以我的问题是,现有的 Dart 类是否可以将客户端 (Secure-)Socket 升级为升级后的 (Secure-)Socket? (然后允许将其转换为 WebSocket 实例)

【问题讨论】:

    标签: websocket dart flutter certificate


    【解决方案1】:

    使用HttpClient 建立初始http(s) 连接,然后使用detach 套接字。这是一个http的例子。你应该能够适应https。请注意初始连接是如何通过 http 建立的,但通过添加适当的请求标头进行升级。 (您需要使标头适应您的 websocket 服务器所需的安全方案。)

      Random r = new Random();
      String key = base64.encode(List<int>.generate(8, (_) => r.nextInt(255)));
    
      HttpClient client = HttpClient(/* optional security context here */);
      HttpClientRequest request = await client.get('echo.websocket.org', 80,
          '/foo/ws?api_key=myapikey'); // form the correct url here
      request.headers.add('Connection', 'upgrade');
      request.headers.add('Upgrade', 'websocket');
      request.headers.add('sec-websocket-version', '13'); // insert the correct version here
      request.headers.add('sec-websocket-key', key);
    
      HttpClientResponse response = await request.close();
      // todo check the status code, key etc
      Socket socket = await response.detachSocket();
    
      WebSocket ws = WebSocket.fromUpgradedSocket(
        socket,
        serverSide: false,
      );
    

    【讨论】:

    • 非常感谢您的详细回答。对于 ws,您的示例在使用 request = await client.get('echo.websocket.org', 80, ""); 时开箱即用。对于任何感兴趣的人,该示例也适用于 wss,方法是使用 Uri uri = Uri.parse("echo.websocket.org:443"); request = await client.getUrl(uri); 请注意,我必须在 parse 命令中使用 https,而不是 wss .
    • 现在 StackOverflow 从 parse 命令中创建了一个链接。重要的部分是它应该以 https://... 开头
    猜你喜欢
    • 2021-08-09
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 2016-03-31
    • 2017-10-18
    • 1970-01-01
    相关资源
    最近更新 更多