Problem ist die Browserunterstützung.
Jedoch kann man die Socket Funktonalität von Flash nach Javascript brigen.
Dann hat man aber auch nur einen Client.
An diesem Punkt kann ich ja mal meine kleine Socket Classe anbringen:
redServerSocket.class.php
PHP-Code:
<?php
class redServerClient
{
private $redServerSocket;
private $commandcache = '';
public $get_history = array();
public $send_history = array();
public $handle;
public $id;
public $lastused;
public $connected;
public $data = array();
public function __construct($redServerSocket, $handle)
{
$this->redServerSocket = $redServerSocket;
$this->handle = $handle;
$this->id = $redServerSocket->getIdFromHandle($handle);
$this->connected = time();
$this->lastused = time();
}
public function addCache($string)
{
$this->lastused = time();
$this->commandcache .= $string;
}
public function getCache()
{
return $this->commandcache;
}
public function clearCache()
{
if(is_array($this->get_history))
$this->get_history[] = substr($this->commandcache, 0, (strlen($this->redServerSocket->end) * -1));
$this->commandcache = '';
}
public function disconnect($code = 3000)
{
@socket_shutdown($this->handle);
@socket_close($this->handle);
$this->redServerSocket->callClientDisconnect($this->id, $code);
$this->redServerSocket->unsetClient($this->id);
return TRUE;
}
public function write($data)
{
$this->redServerSocket->callDataSend($this->id, $data);
if(is_array($this->send_history))
$this->send_history[] = $data;
return socket_write($this->handle, $data);
}
public function send($data)
{
return $this->write($data);
}
public function lastErrorCode()
{
return socket_last_error($this->handle);
}
public function lastErrorString()
{
return socket_strerror($this->lastErrorCode());
}
}
abstract class redServerSocket
{
private $code = array(
'from_api' => 3000,
'timeout' => 3001,
'connection_closed' => 3002,
'connection_refused' => 3003
);
private $mainsocket = NULL;
private $clients = array();
protected $host = 0;
protected $port = 0;
protected $timeout = NULL;
public $end = NULL;
protected function onDataRecieve($clientObj, $data)
{
return TRUE;
}
protected function onDataSend($clientObj, $data)
{
return TRUE;
}
protected function onClientConnect($clientObj)
{
return TRUE;
}
protected function onClientDisconnect($clientObj, $code)
{
return TRUE;
}
protected function onSocketReady($host, $port)
{
}
protected function onSocketError($error, $client = false)
{
}
public function __construct($port = NULL, $host = NULL)
{
if($this->end === NULL)
$this->end = chr(4);
if(false == ($this->mainsocket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP)))
{
$this->onSocketError($this->lastErrorCode());
}
else
{
@socket_set_option($this->mainsocket, SOL_SOCKET, SO_REUSEADDR, 1);
if($port !== NULL)
$this->port = $port;
if($host !== NULL)
$this->host = $host;
if(false == ($ret =@socket_bind($this->mainsocket, $this->host, $this->port)))
{
$this->onSocketError($this->lastErrorCode());
}
else
{
$ret = socket_listen($this->mainsocket);
$this->onSocketReady($this->host, $this->port);
}
}
}
public function callDataSend($id, $data)
{
if(!is_object($id))
$id = $this->clients[$id];
$this->onDataSend($id, $data);
}
public function callClientDisconnect($id, $code)
{
if(!is_object($id))
$id = $this->clients[$id];
$this->onClientDisconnect($id, $code);
}
public function getIdFromHandle($handle)
{
$str = (string)$handle;
$str = substr($str, 13);
return (int)$str;
}
public function getClients()
{
return $this->clients;
}
public function unsetClient($client)
{
unset($this->clients[$client]);
}
public function clientCheck()
{
$localClients = array();
foreach($this->clients as $num => $clientObj)
{
if($this->timeout !== NULL && $clientObj->lastused < time() - $this->timeout && $this->onClientDisconnect($clientObj, $this->code['timeout']))
$clientObj->disconnect($this->code['timeout']);
else
$localClients[$clientObj->id] = $clientObj->handle;
}
$set_r = array_merge((array)$this->mainsocket, $localClients);
$set_w = NULL;
$set_e = $localClients;
// Check for new Data.
// If the mainsocket in the array $set_r
// then is there a new Client!
// If not then is there new Data from the Socket in the Array
if( ( $ret =@socket_select($set_r, $set_w , $set_e , 1) ) > 0 )
{
foreach($set_r as $data)
{
if($data == $this->mainsocket) //Is it the mainsocket there are new clients in it!
{
$newclient = @socket_accept($this->mainsocket);
if($newclient)
{
$id = $this->getIdFromHandle($newclient);
$clientObj = new redServerClient($this, $newclient);
$this->clients[$id] = $clientObj;
if($this->onClientConnect($clientObj) === FALSE)
$clientObj->disconnect($this->code['connection_refused']);
}
else
$this->onSocketError($this->lastErrorCode());
}
else
{
$data_read = socket_read($data, 1024);
$id = $this->getIdFromHandle($data);
if($data_read === false)
{
$ret = $this->onSocketError($this->lastErrorCode(), $this->clients[$id]);
if(!$ret)
$this->clients[$id]->disconnect($this->code['from_api']);
}
else
{
if(strlen($data_read) > 0 && isset($this->clients[$id]))
{
$this->clients[$id]->lastaction = time();
$this->clients[$id]->addCache($data_read);
$endstr_len = strlen($this->end);
if(substr($this->clients[$id]->getCache(), ($endstr_len * -1), $endstr_len) === $this->end)
{
$this->onDataRecieve($this->clients[$id], substr($this->clients[$id]->getCache(), 0, ($endstr_len * -1)));
$this->clients[$id]->clearCache();
}
}
else
$this->clients[$id]->disconnect($this->code['connection_closed']);
}
}
}
foreach($set_e as $handle) //Oh, these Clients have an ugly Error. I kick them from my List!
{
$id = $this->getIdFromHandle($handle);
$this->clients[$id]->disconnect($this->code['connection_closed']);
}
}
}
public function lastErrorCode()
{
return socket_last_error($this->mainsocket);
}
public function lastErrorString()
{
return socket_strerror($this->lastErrorCode());
}
}
?>
redServerSocket.example.class.php
PHP-Code:
<?php
$port = 1338;
include('redServerSocket.class.php');
/*
Metoden der Clients Objekte:
public $get_history = array();
//echo "Dein letztes Komando war: $get_history[0]"
public $send_history = array();
//echo "Ich habe dir zuletzt gesendet: $send_history[0]"
public $handle; //Client Socket Handle. Siehe: http://php.net/manual/de/function.socket-accept.php
public $id; //Client ID
public $lastused; //Unix Timestamp der letzten Client Reaktion.
public $connected; //Unix Timestamp des Verbindungszeitpunktes
public $data = array(); //Ein Array zum Speichern von Session Variablen
public function addCache($string) //Fügt $string zum commandcache hinzu
public function getCache() //Gibt den aktuellen commandcache zurück
public function clearCache() //Löscht den aktuellen commandcache
public function disconnect($code = 3000) //Schliest Verbindung mit Fehlercode
public function write($data) //Sendet Daten an Client. Rückgabe von function: http://de3.php.net/manual/en/function.socket-write.php
public function send($data) //Alias für write($data)
public function lastErrorCode() //Alias für: socket_last_error($this->handle)
public function lastErrorString() //Alias für: socket_strerror(socket_last_error($this->handle))
*/
class Server extends redServerSocket
{
//$this->end = '\n' //Begrenzer der einzelnen Komandos. Standart ist: chr(4) (EOT)
//$this->timeout = 3600; //Zeit in der Client Nachrichten senden muss bevor er aus der Liste geworfen wird.
//NULL deaktiviert das Timeout. Standart ist: NULL
//public function lastErrorCode() //Alias für: socket_last_error($this->mainsocket)
//public function lastErrorString() //Alias für: socket_strerror(socket_last_error($this->mainsocket))
//public function getClients() //return $this->clients.
protected function onDataRecieve($clientObj, $data)
{
if($data == 'Hallo')
$clientObj->data['GREET'] = true;
echo "onDataRecieve [" . $clientObj->id . "]: " . $data . "\n";
$clients = $this->getClients();
foreach($clients as $id => $clientObj)
$clientObj->write('[' . $clientObj->id . ']: ' . $data);
}
protected function onDataSend($clientObj, $data)
{
echo "onDataSend [" . $clientObj->id . "]: " . $data . "\n";
}
protected function onClientConnect($clientObj)
{
echo "onClientConnect [" . $clientObj->id . "]\n";
//$clientObj->get_history = NULL; //Deaktiviert die get_history
//$clientObj->send_history = NULL; //Deaktiviert die send_history
//return FALSE; //Wenn return false wird der client abgelehnt
}
protected function onClientDisconnect($clientObj)
{
echo "onClientDisconnect [" . $clientObj->id . "]\n";
}
protected function onSocketReady($host, $port)
{
echo "Socket ready!!\n";
}
protected function onSocketError($errorcode, $clientObj = false)
{
if($clientObj !== false)
echo "Error [" . $clientObj->id . "]" . $this->lastErrorString(); //Fehler von Client
else
echo "Error" . $this->lastErrorString(); //Fehler von Mainsocket
//return true; //läst den Client, sollte es ein Fehler sein bei dem er normalerweise disconnectet wird, in der Liste;
}
}
echo "Server startet on Port: ".$port."\n" .
"On Liux and Windows Systems you can connect to the server with:\n" .
"telnet <IP> ".$port."\n" .
"You can disconnect by close the Terminal\n" .
"You can shutdown the Server by press CTRL + C in the Server Terminal\n" .
"GL & HF!\n" .
"#######################################################################\n";
$host = NULL;
$socket = new Server($port, $host); //Port und Host. Wenn Host === NULL dann hört der Server auf alle IP Adressen des Hosts
while(true)
{
$socket->clientCheck(); //Prüft auf neue Nachrichten.
}
?>