WebSocket is a feature of HTML5 for establishing socket connections between a web browser and a Server. Once connection has been established with the server, all WebSocket data (frames) are sent directly over a socket rather than usual HTTP response and requests, giving us a much faster and persistent communication between a web browser and a server.
Implementation:
Server: Server is a daemon (that runs in background) using nothing but PHP. In server file, we create a PHP socket which states listening to the clients on a specified port. Server accepts incoming Clients and map their socket ID’s with a unique Client ID in order to send/receive data to and from a specific client.
Client: Client creates a web socket request to server domain and port. After handshake, a persistent connection is established. Client can receive anything sent from the server on real time basis, no need to further request server for updates.
Advantages:
- Instant data passing between server and clients
- Server can push data to any client
- Faster communication between server and clients
- No server overloading with Ajax.
Sample Code:
At Server Side:
Command to run Server file is as follows:
php -q path-to-serverserver.php
$host = 'cr/chat'; //host
$port = '9001'; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
$cc=array();
//create & add listning socket to the list
$clients = array($socket);
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections<br> $changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
{
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text); //json decode
if($tst_msg->type=='system')
{
$cc[$tst_msg->id]=array();
$cc[$tst_msg->id]['name']=$tst_msg->name;
$cc[$tst_msg->id]['soc_id']=$changed_socket;
$response_text =mask(json_encode(array('type'=>'system', 'message'=>'Initial message received')));
send_message($response_text,$changed_socket); //send data
}
else
{
$user_name = $tst_msg->name; //sender name
$user_message = $tst_msg->message; //message text
$user_color = $tst_msg->color; //color
if(isset($cc[$tst_msg->to_id]))
{
$to_sock=$cc[$tst_msg->to_id]['soc_id'];
//prepare data to be sent to client
$response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color)));
send_message($response_text,$to_sock); //send data
}
}
break 2; //exist this loop
}
$buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
//send_message($response);
}
}
}
// close the listening socket
socket_close($sock);
function send_message($msg,$client_socket)
{
@socket_write($client_socket,$msg,strlen($msg));
return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/rn/", $receved_header);
foreach($lines as $line)
{
$line = chop($line);
if(preg_match('/A(S+): (.*)z/', $line, $matches))
{
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshakern" .
"Upgrade: websocketrn" .
"Connection: Upgradern" .
"WebSocket-Origin: $hostrn" .
"WebSocket-Location: ws://$host:$port/server.phprn".
"Sec-WebSocket-Accept:$secAcceptrnrn";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
At Client Side:
Command to run at client side is as follows:
$(document).ready(function(){
//create a new WebSocket object.
var wsUri = "ws://cr:9001/chat/server.php:9000";
websoc2.Client Side
ket = new WebSocket(wsUri);
websocket.onopen = function(ev) { // connection is open
$('#message_box').append("<div class="system_msg">Connected!</div>"); //notify user
//prepare json data
var msg = {
type:'system',
id: 7,
projectId:2424,
na2.Client Side
me:'mks'
};
//convert and send data to server
websocket.send(JSON.stringify(msg));
}
$('#send-b2.Client Side
tn').click(function(){ //use clicks message send button
var mymessage = $('#message').val(); //get message text
var myname = $('#name').val(); //get user name
if(myname == ""){ //empty name?
alert("Enter your Name please!");
return;
}
if(mymessage == ""){ //emtpy message?
alert("Enter Some message Please!");
return;
}
//prepare json data
var msg = {
message: mymessage,
type:'user',
name: 'mks',
id: 7,
projectId:2424,
to_id:5,
color : '<?php echo $colours[$user_colour]; ?>'
};
//convert and send data to server
websocket.send(JSON.stringify(msg));
$('#message_box').append("<div><span class="user_name" style="color:#F00">"+myname+"</span> : <span class="user_message">"+mymessage+"</span></div>");
});
0 Comments