websocketdartdart-webuidart-editor

Dart How to code a simple web-socket echo app


I've been attempting to learn enough html, css, and Dart to create my first web page and all is going well, except that I do not understand how to create a simple page and a server side web-socket server that will just echo it back. The examples that I find tend to illustrate other Dart tools and either connect to echo server on the web or do other things that make their code not simple for a newbie.

I've tried to simplify Seth Ladd's example "dart-example-web-sockets-client" as the 'best' example. I can receive what is sent from the page, repackage it and think i'm sending it back but absolutely nothing happens on the web page. I start the page by clicking on the URL returned when the web-server is run from inside the Dart editor. Since the page is not, AFAIK, run in the debugger I'm hampered in diagnosing the error.

Here is simplified code from Seth's server:

void handleEchoWebSocket(WebSocket webSocket) {
log.info('New WebSocket connection');

// Listen for incoming data. We expect the data to be a JSON-encoded String.
webSocket
  .map((string) => JSON.decode(string))
  .listen((json) {
    // The JSON object should contain a 'request' entry.
     var request = json['request'];
     switch (request) {
       case 'search':  
         var input = json['input'];
         log.info("Received request '$request' for '$input'");
         var response = {
           'response': request,
           'input': input,
      };
      webSocket.add(JSON.encode(response)); // can't detect page receiving this.
      log.info("Echoed request..$request $input"); // correct data
      break;

    default:
      log.warning("Invalid request: '$request'");
      }
    }, onError: (error) {
  log.warning('Bad WebSocket request');
  });
}

This example took the user input using it as input to two search engines, packaged the results and returned them to the page for display creating new DOM elements on the fly.

I just need to be pointed to a simple example that will echo what is submitted.


Solution

  • Here is a simple websocket client/server echo example. Messages doesn't show in browser window, but they are printed in console window. You have to start server.dart and main.dart separately. Both processes print messages to their own console window. Edit: I added an output div for displaying the message also in browser.

    bin\ws_server.dart:

    import "dart:convert";
    import 'dart:io';
    import 'package:route/server.dart' show Router;
    
    
    
    void handleWebSocket(WebSocket webSocket) {
      // Listen for incoming data. We expect the data to be a JSON-encoded String.
      webSocket
        .map((string)=> JSON.decode(string))
        .listen((json) {
          // The JSON object should contains a 'echo' entry.
          var echo = json['echo'];
          print("Message to be echoed: $echo");
          var response='{"response": "$echo"}';
          webSocket.add(response);
        }, onError: (error) {
          print('Bad WebSocket request');
        });
    }
    
    
    void main() {
      int port = 9223;
    
      HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, port).then((server) {
        print("Search server is running on "
                 "'http://${server.address.address}:$port/'");
        var router = new Router(server);
        // The client will connect using a WebSocket. Upgrade requests to '/ws' and
        // forward them to 'handleWebSocket'.
        router.serve('/ws')
          .transform(new WebSocketTransformer())
          .listen(handleWebSocket);
      });
    }
    

    web\index.html:

    <!DOCTYPE html>
    
    <html>
      <head>
        <meta charset="utf-8">
        <title>Websocket echo</title>
      </head>
      <body>
        <p>Websocket test</p>
        <div id="output"></div>
    
        <script type="application/dart" src="main.dart"></script>
      </body>
    </html>
    

    web\main.dart:

    library main;
    
    import 'dart:async';
    import 'dart:convert';
    import 'dart:html';
    
    class WebsocketService {
    
      WebSocket webSocket;
    
      WebsocketService() {
        connect();
      }
    
      void connect() {
        webSocket = new WebSocket('ws://127.0.0.1:9223/ws');
        webSocket.onOpen.first.then((_) {
          onConnected();
          sendws("Hello websocket server");
          webSocket.onClose.first.then((_) {
            print("Connection disconnected to ${webSocket.url}");
            onDisconnected();
          });
        });
        webSocket.onError.first.then((_) {
          print("Failed to connect to ${webSocket.url}. "
                "Please run bin/server.dart and try again.");
          onDisconnected();
        });
      }
    
      void onConnected() {
        webSocket.onMessage.listen((e) {
          onMessage(e.data);
        });
      }
    
      void onDisconnected() {
        print("Disconnected, trying again in 3s");
        new Timer(new Duration(seconds:3), (){
          connect();
        });
      }
    
      void onMessage(data) {
        var json = JSON.decode(data);
        var echoFromServer = json['response'];
        print("Received message: $echoFromServer");
        var output=querySelector('#output');
        output.text="Received message: $echoFromServer";
    
        new Timer(new Duration(seconds:3), (){ //Send a new message to server after 3s
          String now = new DateTime.now().toString();
          sendws("Time: $now");
        });
    
      }
    
      void sendws(String msg){
        var request = '{"echo": "$msg"}';
        print("Send message to server: $request");
        webSocket.send(request);
      }
    }
    
    void main() {
      WebsocketService ws=new WebsocketService();
    }