Wednesday, December 21, 2011

PHP5 WebSocket Example – A Simple Chat

The classic example for websockets is a chat. This chat example has only 200 lines of code (excl. the Websocket class), is really easy to understand and customizable.

The WebSocket class takes a function (or class method) as callback for every socket action, for this example i use the process method of the WebsocketChat Class:
 
$chat = new WebsocketChat();
// new WebSocketServer( socket address, socket port, callback function )
$webSocket = new WebSocketServer("84.38.67.247", 8081, array($chat, 'process'));
$webSocket->run();
The WebsocketChat Class handles user actions and messages. We have two actions: ‘login’ and ‘chat’. ‘login’ happens when a new user sets his username, ‘chat’ is always when a user sends a new message:
 
Class WebsocketChat {
 
 /**
  * @var array
  */
 private $messages = array();
 
 public function process($user, $msg, $server){
 
  $msg = json_decode($msg);
 
  if ($msg->action == 'login') {
 
  }
 
  if ($msg->action == 'chat') {
 
  }
 }
}
On the client-side we have to send the right actions if someone clicks ‘login’ or ‘send message’.
 
$('#chat').submit(function(evt){
 evt.preventDefault();
 send({'action':'chat', 'text':$('[name=text]').val()});
});
 
$('#login').submit(function(evt){
 evt.preventDefault();
 send({'action':'login', 'username':$('[name=username]').val()});
 $('#chat').show();
 $('#login').hide();
});
The login action adds a new chat user to the user-array and loads the last five messages for this new user.
 
if ($msg->action == 'login') {
 $user->data['username'] = filter_var($msg->username, FILTER_SANITIZE_STRING);
 
 $max = 5;
 if (count($this->messages)<5)
  $max = count($this->messages);
 
 // on login send last five chat messages
 for($i=count($this->messages)-$max; $i<count($this->messages); $i++) {
  $server->send($user->socket, (string) $this->messages[$i]);
 }
}
If the ‘chat’ action is called then add a new WebsocketChatMessage to the message array and send it to all current chat-users:
 
if ($msg->action == 'chat') {
 $text = filter_var($msg->text, FILTER_SANITIZE_STRING); 
 $lastMessage = new WebsocketChatMessage($user->data['username'], $text, time());
 
 $user->data['message'][] = $this->messages[] = $lastMessage;
 
 foreach($server->getUsers() as $user){
  $server->send($user->socket, (string) $lastMessage);
 }   
}
The WebsocketChatMessage is just a container-class for holding the message data:
 
Class WebsocketChatMessage {
 
 public $text = '';
 
 public $timestamp = 0;
 
 public $username = '';
 
 public function __construct($username, $text, $timestamp) {
  $this->text = $text;
  $this->username = $username;
  $this->timestamp = $timestamp;
 }
 
 public function __toString() {
  return sprintf('%s %s: %s', strftime('%H:%M', $this->timestamp), $this->username, $this->text);
 }
}
View Chat Example on BOHUCO Labs
View server.php Code

No comments:

Post a Comment