/    Sign up×
Community /Pin to ProfileBookmark

PHP Socket Server

Okay i created a HTTP Ajax chat a while back and its really hitting my web server hard, its created using memcache to store the data in but still hits the server hard.

Im wanting to create a php socket run it on my server then either use java or flash for the users to connect to the socket since javascript dont support sockets(annoying !)

I quickly found content on php sockets to be somewhat outdated and quickly tried to create a class based on the functions to give me catchable methods instead of functions which just error….

[code=php]<?php

interface iSocket {
public static function create($domain, $type, $protocol);
public static function bind($socket, $address, $port);
public static function listen($socket);
public static function write($socket, $uffer);
public static function close($socket);
public static function read($socket, $length);
public static function accept($socket);
public static function select(array &$read, array &$write, array &$except, $tv_sec);
public static function getpeername($socket, &$ip, &$port=null);

}

class socket implements iSocket {

/**
*
* @param <static> $domain
* @param <static> $type
* @param <static> $protocol
* @return <resource>
*/
public static function create($domain, $type, $protocol) {
$resource = @socket_create($domain, $type, $protocol);

if (self::_isResource($resource)) {
return $resource;
}

throw new Exception(‘Failed to create socket on ‘ . $domain . ‘, type ‘ . $type . ‘, protocol ‘ . $protocol . “nn”);
}

/**
*
* @param <resource> $socket
* @param <string> $address
* @param <integer> $port
* @return <bool>
*/
public static function bind($socket, $address, $port) {
if (self::_isResource($socket)) {
$status = @socket_bind($socket, $address, $port);

if ($status) {
return (bool) true;
}
}

throw new Exception(‘Failed to bind socket to ‘ . $address . ‘ on port ‘ . $port . “nn”);
}

/**
*
* @param <resource> $socket
* @return <bool>
*/
public static function listen($socket) {
if (self::_isResource($socket)) {
$status = @socket_listen($socket);

if ($status) {
return $status;
}
}

throw new Exception(‘Failed to listen’);
}

/**
*
* @param <resource> $socket
* @return <bool>
*/
public static function close($socket) {
if (self::_isResource($socket)) {
@socket_shutdown($socket, 2);
return (bool) @socket_close($socket);
}

return (bool)false;
}

/**
*
* @param <resource> $socket
* @param <string> $buffer
* @return <bool>
*/
public static function write($socket, $buffer) {
if (self::_isResource($socket)) {
$return = @socket_write($socket, $buffer, strlen($buffer));

if ($return) {
return (bool) true;
}
}

return (bool) false;
}

/**
*
* @param <resource> $socket
* @param <integer> $length
* @return <mixed>
*/
public static function read($socket, $length) {
if (self::_isResource($socket)) {
@socket_recv($socket, $data, $length, MSG_DONTWAIT);

if ($data != null) {
return $data;
}
}

return (bool) false;
}

/**
*
* @param <resource> $socket
* @return <mixed>
*/
public static function accept($socket) {
if (self::_isResource($socket)) {
$return = @socket_accept($socket);

if (is_resource($socket)) {
return $return;
}
}

return (bool) false;
}

/**
*
* @param <array> $read
* @param <array> $write
* @param <array> $except
* @param <integer> $tv_sec
* @return <mixed>
*/
public static function select(array &$read, array &$write, array &$except, $tv_sec=0) {
$return = @socket_select($read, $write, $except, $tv_sec);

if ((is_numeric($return)) && ($return > 0)) {
return (int) $return;
}

return (bool) false;
}

/**
*
* @param <resource> $socket
* @param <mixed> $ip
* @param <integer> $port
* @return <bool>
*/
public static function getpeername($socket, &$ip, &$port = null) {
if (self::_isResource($socket)) {
$return = @socket_getpeername($socket, $ip, $port);

if($return){
return (bool)true;
}
}

return (bool)false;
}

/**
*
* @param <resource> $socket
* @return <bool>
*/
private static function _isResource($socket){
if(is_resource($socket)){
return (bool)true;
}

return (bool)false;
}

}

?>
[/code]

So once i had created those static methods i then played with the class but had some very odd results, sometimes it would work yet others would just fail…im using a VPS server on debian i setup myself PHP is complied with sockets.

I came up with this…but its not very stable its working sometimes but other times its not.

[code=php]<?php

class chatServer {

private $_socket;
private $_clients;
private $_maxConnections;
private $_position;

public function __construct($bind, $port, $maxConnections=10) {
try {
$this->_socket = socket::create(AF_INET, SOCK_STREAM, SOL_TCP);
socket::bind($this->_socket, ‘127.0.0.1’, 5190);
socket::listen($this->_socket);

$this->_clients = array($this->_socket);
$this->_position = 1;
$this->_maxConnections = $maxConnections;
} catch (Exception $e) {
die($e->getMessage());
}
}

public function listen() {
$read = $this->_clients;

$status = socket::select($read, $write=array(), $except=array(), 0);

if($status){
if (in_array($this->_socket, $read)) {
$this->_clients[$this->_position] = new stdClass();
$this->_clients[$this->_position]->socket = socket_accept($this->_socket);

socket::write($this->_clients[$this->_position]->socket, “Connectedn”);
socket::getpeername($this->_clients[$this->_position]->socket, $this->_clients[$this->_position]->address);

$key = array_search($this->_socket, $read);
unset($read[$key]);

$this->_position++;
}
}

sort($this->_clients);
$clients = count($this->_clients);

for($i=1;$i<$clients;++$i){
if(is_object($this->_clients[$i])){
$data = socket::read($this->_clients[$i]->socket, 256);

if($data){//found data
foreach($this->_clients as $client){//send data to all current clients
if(is_object($client)){
socket::write($client->socket, trim($data).”n”);
}
}
}else{
socket::close($this->_clients[$i]->socket);
unset($this->_clients[$i]);
}
}

}

return count($this->_clients).”n”;
}

}
?>[/code]

The class is mainly built with bits around the internet but sadly that was all PHP4…im finding the documentation somewhat lacking aswell

Can anyone help ive also just noticed stream_socket_server() which came into PHP5 is this some kind of new versions ?

to post a comment
PHP

3 Comments(s)

Copy linkTweet thisAlerts:
@DexterMorganFeb 01.2011 — Popped up in my RSS feed today, might be some help http://bohuco.net/blog/2011/01/php5-websocket-example-a-simple-chat/
Copy linkTweet thisAlerts:
@tuseroniFeb 01.2011 — sadly i think websockets will be going away. i have been waiting for them but firefox has dropped support, i dont think ie intends to support it, only chrome supports it that i know of (maybe all of webkit..)

this has worked well for me:

http://pastebin.com/E40Gj0Uj

as you may tell its based in part on the websocket server file with some modifications.

you run it by typing "./[scriptname].php&" in a command prompt

for my chat i like to use this php to communicate with the sockets and put out the results to firefox (its not cross platform)

http://pastebin.com/gTvLDvVp

then ajax to that script, each time something changes it puts out a new header and the content, ajax then calls onreadystatechange and i can respond to that change.

i can push changes using another php script that writes to the socket and optionally saves it to a database.

when the push script writes to the socket, the socket server script propagates those changes to everyone connected.

ive never really noticed performance issues even with a good number of connections and (simulated)heavy traffic

but you can still use java or flash and just the server and it should work (ive tested it with clients coming from a compiled program and with something like this in a compiled program acting as the server)

remember when using it that all writes need to end with character 255, thats when it knows to stop reading...
×

Success!

Help @gavshouse spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.7,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...