Websockets with php – tutorial on basics
Websockets
Websockets is a new feature available in browsers as a part of the Html5 specs that allows javascript clients to open bi directional socket connections to a server. Currently all major desktop browsers support the api.
Websocket is not an independant socket protocol, but is based on the TCP protocol just like HTTP. Therefore websocket connections are basically tcp socket connections that following the websocket rules to communicate. The protocol is is documented at RFC 6455.
So a separate socket server is needed to handle the websocket communications. The same web/http server like apache would not do that. Websocket server are run like normal daemons on linux for example.
Websocket url
A websocket url looks like this
The important parts are host and port. It should be noted that the uri part after port is not necessary to establish the connection. It should not be confused to point to the path of the php server script or anything. It can be used by the server to locate resources. The connection is just made to the host on the given port number.
Now lets try to code up something using websockets.
Code
We shall use the following websocket server, written in php
https://github.com/ghedipunk/PHP-WebsocketsThe server itself is a class that can be extended to write the rest of the application. Download the zip and look inside. The websockets.php is the base class and we shall extend that class to write our own simple websocket server application. The base class does the socket management and websocket handshake stuff etc.
The application class just needs to override the process function to handle the incoming requests from the client.
#! /usr/local/bin/php
<?php
require_once('websockets.php');
class echo_server extends WebSocketServer
{
//protected $maxBufferSize = 1048576; //1MB... overkill for an echo server, but potentially plausible for other applications.
protected function process ($user, $message)
{
if($message == 'help')
{
$reply = 'Following commands are available - date, hi';
}
else if($message == 'date')
{
$reply = "Current date is " . date('Y-m-d H:i:s');
}
else if($message == 'hi')
{
$reply = "Hello user. This is a websocket server.";
}
else
{
$reply = "Thank you for the message : $message";
}
$this->send($user, $reply);
//The uri component say /a/b/c
echo "Requested resource : " . $user->requestedResource . "n";
}
/**
This is run when socket connection is established. Send a greeting message
*/
protected function connected ($user)
{
//Send welcome message to user
$welcome_message = 'Hello. Welcome to the Websocket server. Type help to see what commands are available.';
$this->send($user, $welcome_message);
}
/**
This is where cleanup would go, in case the user had any sort of
open files or other objects associated with them. This runs after the socket
has been closed, so there is no need to clean up the socket itself here.
*/
protected function closed ($user)
{
echo "User closed connectionn";
}
}
$host = '0.0.0.0';
$port = 9000;
$server = new echo_server($host , $port );
Now launch the server script from terminal
php /var/www/blog/websocket/echo_server.php
Once launched it shall open a socket server on 9000 that will speak the "websocket" protocol and supporting browsers can talk to it.
Next comes the client, that would be written in javascript. Here is the code
<html>
<head>
<title>WebSocket</title>
<style type="text/css">
#log {
width:600px;
height:300px;
border:1px solid #7F9DB9;
overflow:auto;
padding:10px;
}
#msg {
width:300px;
}
</style>
<script type="text/javascript">
var socket;
function init() {
var host = "ws://localhost:9000/path/to/app"; // SET THIS TO YOUR SERVER
try
{
socket = new WebSocket(host);
log('WebSocket - status ' + socket.readyState);
socket.onopen = function(msg)
{
if(this.readyState == 1)
{
log("We are now connected to websocket server. readyState = " + this.readyState);
}
};
//Message received from websocket server
socket.onmessage = function(msg)
{
log(" [ + ] Received: " + msg.data);
};
//Connection closed
socket.onclose = function(msg)
{
log("Disconnected - status " + this.readyState);
};
socket.onerror = function()
{
log("Some error");
}
}
catch(ex)
{
log('Some exception : ' + ex);
}
$("msg").focus();
}
function send()
{
var txt, msg;
txt = $("msg");
msg = txt.value;
if(!msg)
{
alert("Message can not be empty");
return;
}
txt.value="";
txt.focus();
try
{
socket.send(msg);
log('Sent : ' + msg);
}
catch(ex)
{
log(ex);
}
}
function quit()
{
if (socket != null)
{
log("Goodbye!");
socket.close();
socket=null;
}
}
function reconnect()
{
quit();
init();
}
// Utilities
function $(id)
{
return document.getElementById(id);
}
function log(msg)
{
$('log').innerHTML += '<br />' + msg;
$('log').scrollTop = $('log').scrollHeight;
}
function onkey(event)
{
if(event.keyCode==13)
{
send();
}
}
</script>
</head>
<body onload="init()">
<h3>WebSocket</h3>
<div id="log"></div>
Enter Message <input id="msg" type="textbox" onkeypress="onkey(event)"/>
<button onclick="send()">Send</button>
<button onclick="quit()">Quit</button>
<button onclick="reconnect()">Reconnect</button>
</body>
</html>
The WebSocket class is used to created an object of websocket. It takes the websocket url as the parameter to connect. Then there are events like 'onopen', 'onmessage' , 'onclose' that need to be handled.
The communication can look like this
WebSocket - status 0 We are now connected to websocket server. readyState = 1 [ + ] Received: Hello. Welcome to the Websocket server. Type help to see what commands are available. Sent : help [ + ] Received: Following commands are available - date, hi Sent : hi [ + ] Received: Hello user. This is a websocket server. Sent : date [ + ] Received: Current date is 2013-02-13 10:31:58 Sent : how are you [ + ] Received: Thank you for the message : how are you
Conclusion
The main power of websockets lies in its ability to do bidirectional communication without breaking the connection. Therefore it can be used to implement realtime communication like chat without polling.
Related Posts
-
http://www.hexabit.pl/ michal przybylowicz
-
http://www.binarytides.com/ Silver Moon
-