-
Notifications
You must be signed in to change notification settings - Fork 580
Writing websocket chat using Mojolicious Lite
Note: This page is a translation of http://d.hatena.ne.jp/naoya/20101011/1286778922.
I read the article (real time web with websocket http://www.atmarkit.co.jp/fcoding/articles/websocket/01/websocket01a.html) The article says, you can easily write event driven web server when you use Javascript framework, which is using V8 and named node.js
. Additionally, using node-websocket-server.js
, you can easily implement websocket server with node.js
. The article compares architecture of websocket, polling with Ajax and long polling.
(Please look at the reference material at the end of this article for links)
Websocket enables us to write server-pushing application easily. But the problem is how to prepare the HTTP server which processing websocket. It is interesting that node.js is one of the answer.
The article provoked me into writing server-side program in Perl, not Javascript. I wrote a sample using Mojolicious::Lite. Mojolicious includes an implementation of a server that can handle the WebSocket protocol.
So you can write it like below.
use Mojolicious::Lite;
websocket '/echo' => sub {
my $self = shift;
$self->on(message => sub {
my ($self, $message) = @_;
$self->send("echo: $message");
});
};
app->start;
Then, starting the server,
% perl app.pl daemon
ws://localhost:3000/echo
is the end point of websocket. The callback passed to receive_message()
will be kicked on every event from client-side. Other processes like handshaking are treated appropriately by Mojo. It's offhandedness.
The following is the chat I made as a sample. /
returns HTML chat page. /echo
is the websocket endpoint. When it receives a message, it sends the time and the received message to all connected clients.
#!/usr/bin/env perl
use utf8;
use Mojolicious::Lite;
use DateTime;
get '/' => 'index';
my $clients = {};
websocket '/echo' => sub {
my $self = shift;
app->log->debug(sprintf 'Client connected: %s', $self->tx);
my $id = sprintf "%s", $self->tx;
$clients->{$id} = $self->tx;
$self->on(message => sub {
my ($self, $msg) = @_;
my $dt = DateTime->now( time_zone => 'Asia/Tokyo');
for (keys %$clients) {
$clients->{$_}->send({json => {
hms => $dt->hms,
text => $msg,
}});
}
});
$self->on(finish => sub {
app->log->debug('Client disconnected');
delete $clients->{$id};
});
};
app->start;
__DATA__
@@ index.html.ep
<html>
<head>
<title>WebSocket Client</title>
<script
type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"
></script>
<script type="text/javascript" src="/js/ws.js"></script>
<style type="text/css">
textarea {
width: 40em;
height:10em;
}
</style>
</head>
<body>
<h1>Mojolicious + WebSocket</h1>
<p><input type="text" id="msg" /></p>
<textarea id="log" readonly></textarea>
</body>
</html>
The client side js code is below. Connecting to /echo
with websocket API, processes input and output appropriately.
$(function () {
$('#msg').focus();
var log = function (text) {
$('#log').val( $('#log').val() + text + "\n");
};
var ws = new WebSocket('ws://localhost:3000/echo');
ws.onopen = function () {
log('Connection opened');
};
ws.onmessage = function (msg) {
var res = JSON.parse(msg.data);
log('[' + res.hms + '] ' + res.text);
};
$('#msg').keydown(function (e) {
if (e.keyCode == 13 && $('#msg').val()) {
ws.send($('#msg').val());
$('#msg').val('');
}
});
});
Access to localhost:3000 with Google Chrome. It works fine.
Screenshot: http://f.hatena.ne.jp/naoya/20101011153308
In this way you can implement a WebSocket server with Perl. As I end on that, there is a wealth of existing information to make use of which give rise to a number of different ideas. Such as implementing on a server in Perl something like the Activity Monitor that article mentioned. I'm never out of ideas, such as displaying a remote server's status graphically.
- More Mojolicious WebSocket example / No time to wait
-
http://vti.showmetheco.de/articles/2010/05/more-mojolicious-websocket-examples.html
You can find more gorgeous samples using Mojolicious + websocket.
- Twiggy sample
-
http://cpansearch.perl.org/src/MIYAGAWA/Twiggy-0.1007/eg/chat-websocket/chat.psgi
When I search another server-side example, I found Twiggy (AnyEvent + PSGI based) sample. It's happy to process websocket with Plack/PSGI.
- "The Realtime Web"
-
http://www.atmarkit.co.jp/fcoding/articles/websocket/01/websocket01a.html
An eye on WebSocket "The Realtime Web" - original article (jp)
- node.js
-
Server-side JavaScript framework
- node-websocket-server.js
-
http://github.com/miksago/node-websocket-server
Server for the websocket protocol