Working with WebSocket
Tags: javascript, node, webdev, dart
Published: 2019-04-26 20:54:37

---
title: Working with WebSocket
published: true
description: Implementing Client & Server side WebSocket with Dart
tags: javascript, nodejs, webdev, dart
---

## init
*WebSocket* -- used in real-time data transfer scenarios, such as multiplayer games/ chatbots/ sensor network in IoT etc.

### define
Well, *WebSocket* is simply a general *HTTP* connection with some modifications, where a normal *HTTP* connection gets upgraded to *WebSocket* connection, when two communicating *PEERs* agree to use a single socket for all their communication, followed by a handshake. It could be thought of as a bidirectional communication channel in between two *PEERs*. When communication ends, that socket is destroyed.

## idea
May be you've already worked with *WebSocket* using *NodeJS* or *Java* or *PHP* or *Python* or something else, but today we're going to use *Dart Language* for implementing both *WebSocket Server & Client* in a much easier way.

Alright so let's get into coding ...

## implement
First we're going to write a *WebSocket Server*

### WebSocket Server
As I've already said, *WebSocket* is a modified version of a *HTTP* connection, we're going to create a *HttpServer* and then we'll upgrade that connection to *WebSocket*.

```dart
import 'dart:io' show HttpServer, HttpRequest;
main() {
  HttpServer.bind('localhost', 8000).then((HttpServer server) {
      // httpserver listens on http://localhost:8000
    print('[+]HttpServer listening at -- http://localhost:8000');
    server.listen((HttpRequest request) {
       
       // more code goes here

    }, onError: (err) => print('[!]Error -- ${err.toString()}'));
  }, onError: (err) => print('[!]Error -- ${err.toString()}'));
}
```
Now we've *HttpRequest* object, which is going to be upgraded to *WebSocket*.
```dart
import 'dart:io' show WebSocket, WebSocketTransformer;
import 'dart:convert' show json;
import 'dart:async' show Timer;
// will put this snippet with in main()
WebSocketTransformer.upgrade(request).then((WebSocket ws) {
    // upgradation happens here and now we've a WebSocket object
        ws.listen( // listening for data
          (data) {
            print(
                '\t\t${request?.connectionInfo?.remoteAddress} -- ${Map<String, String>.from(json.decode(data))}'); // client will send JSON data
            Timer(Duration(seconds: 1), () {
              if (ws.readyState == WebSocket.open)
                ws.add(json.encode({
                  'data': 'from server at ${DateTime.now().toString()}', // in response JSON data is sent back to client
                })); // Timer helps to schedule code execution
            });
          },
          onDone: () => print('[+]Done :)'),
          onError: (err) => print('[!]Error -- ${err.toString()}'),
          cancelOnError: true,
        );
      }, onError: (err) => print('[!]Error -- ${err.toString()}'));
```
See it's this much easy to upgrade a *HTTP* connection to *WebSocket* connection, with *Dart* :heart:.

Here's our whole *WebSocket Server* code.
```dart
import 'dart:io' show HttpServer, HttpRequest, WebSocket, WebSocketTransformer;
import 'dart:convert' show json;
import 'dart:async' show Timer;

main() {
  HttpServer.bind('localhost', 8000).then((HttpServer server) {
    print('[+]WebSocket listening at -- ws://localhost:8000/');
    server.listen((HttpRequest request) {
      WebSocketTransformer.upgrade(request).then((WebSocket ws) {
        ws.listen(
          (data) {
            print(
                '\t\t${request?.connectionInfo?.remoteAddress} -- ${Map<String, String>.from(json.decode(data))}');
            Timer(Duration(seconds: 1), () {
              if (ws.readyState == WebSocket.open)
              // checking connection state helps to avoid unprecedented errors
                ws.add(json.encode({
                  'data': 'from server at ${DateTime.now().toString()}',
                }));
            });
          },
          onDone: () => print('[+]Done :)'),
          onError: (err) => print('[!]Error -- ${err.toString()}'),
          cancelOnError: true,
        );
      }, onError: (err) => print('[!]Error -- ${err.toString()}'));
    }, onError: (err) => print('[!]Error -- ${err.toString()}'));
  }, onError: (err) => print('[!]Error -- ${err.toString()}'));
}
```

Let's go for *WebSocket Client*.

### WebSocket Client
Now *Dart* has got a class *WebSocket* in *dart:io*, which takes care of implementation of *WebSocket Client*, does all the heavy liftings for us :hammer_and_pick:.

You can assume, implementation of *WebSocket Client* will be much easier.

```dart
import 'dart:io' show WebSocket;
import 'dart:convert' show json;
import 'dart:async' show Timer;

main() {
  WebSocket.connect('ws://localhost:8000').then((WebSocket ws) {
      // our websocket server runs on ws://localhost:8000
    if (ws?.readyState == WebSocket.open) {
        // as soon as websocket is connected and ready for use, we can start talking to other end
      ws.add(json.encode({
        'data': 'from client at ${DateTime.now().toString()}',
      })); // this is the JSON data format to be transmitted
      ws.listen( // gives a StreamSubscription
        (data) {
          print('\t\t -- ${Map<String, String>.from(json.decode(data))}'); // listen for incoming data and show when it arrives
          Timer(Duration(seconds: 1), () {
            if (ws.readyState == WebSocket.open) // checking whether connection is open or not, is required before writing anything on socket
              ws.add(json.encode({
                'data': 'from client at ${DateTime.now().toString()}',
              }));
          });
        },
        onDone: () => print('[+]Done :)'),
        onError: (err) => print('[!]Error -- ${err.toString()}'),
        cancelOnError: true,
      );
    } else
      print('[!]Connection Denied');
      // in case, if serer is not running now
  }, onError: (err) => print('[!]Error -- ${err.toString()}'));
}

```

Wasn't it easier than *WebSocket Server* implementation ?

And yes, with **930 bytes** of client-side Dart code and **1175 bytes** of server-side Dart code, we've completed *WebSocket* implementation.

## run
Make sure you've installed *Dart SDK* from [here](https://www.dartlang.org/tools/sdk) and set *PATH* variable properly.

Time to run these beasts :laughing:

```bash
$ dart websocket_server.dart
```
And in another terminal
```bash
$ dart websocket_client.dart
```
And :boom:

![websocket client-server on run](https://thepracticaldev.s3.amazonaws.com/i/isuke2pbyjupnwenft1l.gif)

## end
In this article, you've learnt how to use *Dart* for building *WebSocket* Peers, for tranferring real-time data.

> Got any problems ?

> Yes

> Find me on [Twitter](https://twitter.com/meanjanry)

Wrap up time. See you in next article.

In the mean time, you may check out my *GitHub* [profile](https://github.com/itzmeanjan/) for my other projects.