Dart How to code a simple web-socket echo app
Asked Answered
M

2

10

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.

Marshland answered 14/3, 2014 at 23:27 Comment(0)
R
14

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();
}
Relive answered 15/3, 2014 at 8:24 Comment(4)
I think that this is exactly what I needed. Serendipitously you used 'library main;' which motivated this newbie to re-read 'A Tour of the Dart Libraries' and pick up some details I ignored the first times around.Marshland
@natelockwood Glad I could help, I was fiddling around with websockets when you placed your question.Relive
This answer is now out of date because the Dart package 'route' is discontinued. This stack overflow answer has a better websocket server implementation: https://mcmap.net/q/1164228/-echo-websocket-in-dart And if you just want to test the server, you can use the browser-bsed websocket client on this page websocket.org/echo.htmlAdventurism
But the main.dart part is still how one would do this today?Osteitis
T
0

You can try using this package now: https://pub.dev/packages/websocket_universal

Simple example as follows:

// ignore_for_file: avoid_print
import 'package:websocket_universal/websocket_universal.dart';

/// Example works with Postman Echo server
void main() async {
  /// 1. Create webSocket handler:
  final textSocketHandler = IWebSocketHandler<String, String>.createClient(
    'wss://ws.postman-echo.com/raw', // Postman echo ws server
    SocketSimpleTextProcessor(),
  );

  /// 2. Listen to webSocket messages:
  textSocketHandler.incomingMessagesStream.listen((inMsg) {
    print('> webSocket  got text message from server: "$inMsg" '
        '[ping: ${textSocketHandler.pingDelayMs}]');
  });
  textSocketHandler.outgoingMessagesStream.listen((inMsg) {
    print('> webSocket sent text message to   server: "$inMsg" '
        '[ping: ${textSocketHandler.pingDelayMs}]');
  });

  /// 3. Connect & send message:
  await textSocketHandler.connect();
  textSocketHandler.sendMessage('Hello server!');
  await Future<void>.delayed(const Duration(seconds: 4));

  // 4. Disconnect & close connection:
  await textSocketHandler.disconnect('manual disconnect');
  textSocketHandler.close();
}
Tedium answered 18/6, 2023 at 12:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.