Working with WebSocket
Anjan Roy
Posted on April 26, 2019
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.
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.
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 ❤️.
Here's our whole WebSocket Server code.
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 ⚒️.
You can assume, implementation of WebSocket Client will be much easier.
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 and set PATH variable properly.
Time to run these beasts 😆
$ dart websocket_server.dart
And in another terminal
$ dart websocket_client.dart
And 💥
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
Wrap up time. See you in next article.
In the mean time, you may check out my GitHub profile for my other projects.
Posted on April 26, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.