Dart/Flutter WebSocket 服务器/客户端在同一侧无法正常工作

Posted

技术标签:

【中文标题】Dart/Flutter WebSocket 服务器/客户端在同一侧无法正常工作【英文标题】:Dart/Flutter WebSocket server/client is not working properly in the same side 【发布时间】:2020-07-02 20:18:19 【问题描述】:

我正在尝试为我的兴趣开发一个 oauth2 演示。在演示中,当用户点击授权服务器时,授权服务器将重定向 url 返回给我。在我的服务器中,我为此重定向 url 保留了一个端点。在此端点中,我获取请求的查询参数并通过 web_socket_channel 连接到 websocket。连接后,我将查询参数数据发送到 Web 套接字。下面我将添加实现。

import 'package:aqueduct/aqueduct.dart';
import 'package:web_socket_channel/web_socket_channel.dart' as ws;
class AuthorizationController extends ResourceController
  static final uri = Uri(scheme: 'ws',host: 'localhost',pathSegments: ['connect'],port: 8888);

  @Operation.get()
  Future<Response> manageRedirection()async
    Map<String,dynamic> map = request.raw.uri.queryParameters;
    sendToWs(map);
    return Response.ok(map.toString());
  

  void sendToWs(Map<String,dynamic> map)
    final channel =ws.WebSocketChannel.connect(uri);
    print("AuthorizationController: data -> $map");
    channel.sink.add(map);
  

现在在服务器端(http 服务器的 /connect 端点为此保留)我升级传入请求并创建一个 WebSocketClient 实例并将该实例添加到列表中。下面我将展示升级部分和WebSocketClient

List<WebsocketClient> clients =  [];

class Oauth2demoserverChannel extends ApplicationChannel 
  @override
  Future prepare() async 
    logger.onRecord.listen((rec) => print("$rec $rec.error ?? "" $rec.stackTrace ?? """));

  
  @override
  Controller get entryPoint 
    final router = Router();

    router
      .route("/redirection")
      .link(() => AuthorizationController());

    router
      .route("/connect")
      .linkFunction((request) async 
        void handleWebSocket(WebSocket webSocket)
          var newC = WebsocketClient(webSocket);
          clients.add(newC);
          print("clients map:$clients.asMap()");
        
        // ignore: close_sinks
        // ignore: unused_local_variable
        final socket = await WebSocketTransformer.upgrade(request.raw)
          .then(handleWebSocket);
      return null;
      );
    return router;
  

以上部分是关于 Dart Aqueduct 框架及其路由的。我为授权服务器的重定向作业保留了/redirection 端点。我在该端点上获取数据,正如我们在第一个代码部分中看到的那样,我将自己连接到 ws://localhost:8888/connect 并添加数据。

现在我将向您展示这些WebSocketClientClass。此类在构造函数中获取一个 websocket 实例并开始侦听。消息到达时; messageHandler获取列表中的所有 Web 套接字客户端并广播消息。

import 'package:oauth2demoserver/oauth2demoserver.dart';
import 'package:oauth2demoserver/channel.dart' as ch;

class WebsocketClient
  WebsocketClient(WebSocket ws)
    _webSocket = ws;
    

    _webSocket.listen(messageHandler,onError: errorHandler,onDone: finishHandler);
  
  WebSocket _webSocket;

  void messageHandler(dynamic data)
    for(WebsocketClient wsc in ch.clients)
      if( wsc != this)
        wsc._webSocket.add(data);
      

    
  

  void errorHandler(error)
    print("err");
    _webSocket.close();
  

  void finishHandler()
    print("finished");
    _webSocket.close();
  

另一方面,我现在有一个单独的 Flutter 应用程序。在该应用程序中,我连接到ws://localhost:8888/connect,我可以收听或添加一些内容,并且在服务器中WebSocketClient 可以处理消息并广播它。但是当我尝试使用一些查询参数点击http://localhost:8888/redirection 时,为该重定向新创建的WebSocketClient 实例不会进入messageHandler 函数,而是转到onDone。因为这些消息永远不会进入任何渠道。我想知道为什么会这样,知道吗?我将添加一张图片,显示对/redirection 端点的调用的反应。 /redirection end point takes the query parameters end sends to web socket server for broadcating but it is not as we can see in this picture

注意:我还在 /redirect 端点尝试了另一个连接包,该客户端给出了错误代码 1005,它可能会有所帮助。

编辑:我也尝试过使用 javascript 和 python web socket 服务器。所以看起来服务器配置没有问题。我想关于http服务器有一个小技巧。仍在等待帮助,谢谢。

【问题讨论】:

【参考方案1】:

我解决了这个问题。似乎在我将数据发送到 websocket 的 AuthorizationController(第一个代码部分)中,我需要对数据应用 json 编码。

channel.sink.add(json.encode(map));

【讨论】:

以上是关于Dart/Flutter WebSocket 服务器/客户端在同一侧无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在Dart / flutter中映射和显示嵌套的JSON?

如何在 dart/flutter 中解码 json 数组?

如何在 dart/flutter 中解码复杂的 json?

Dart/Flutter 替代 PHP 调整裁剪图像大小?

《Dart Flutter教程》

在 Dart / Flutter 中解析嵌套的 XML