12-01-2009, 11:33 PM
Voici un petit serveur Socket en PHP construit dans l'objectif d'interagir avec Flash (via XMLSocket).
Il se constitue de deux classes: SocketServer et Logger.
SocketServer gere le server en tant que tel, les methods sont simples, et pour le "customiser" il suffit d'ajouter sa gestion de requete dans la method parseRequest (l'idéal etant d'avoir une classe pour le faire)
Il se constitue de deux classes: SocketServer et Logger.
SocketServer gere le server en tant que tel, les methods sont simples, et pour le "customiser" il suffit d'ajouter sa gestion de requete dans la method parseRequest (l'idéal etant d'avoir une classe pour le faire)
Code PHP :
<?php
class SocketServer
{
var $ip;
var $port;
var $masterSocket;
var $logger;
private $currentSockets;
function __construct($ip, $port)
{
$this->ip = $ip;
$this->port = $port;
$this->logger = Logger::getInstance();
$this->initSocket();
$this->currentSockets = array();
$this->currentSockets[] = $this->masterSocket;
$this->listenToSockets();
}
private function initSocket()
{
if (($this->masterSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0)
{
$this->logger->log("[SocketServer] "."socket_create() failed, reason: " . socket_strerror($this->masterSocket));
}
socket_set_option($this->masterSocket, SOL_SOCKET,SO_REUSEADDR, 1);
if (($ret = socket_bind($this->masterSocket, $this->ip, $this->port)) < 0) {
$this->logger->log("[SocketServer] "."socket_bind() failed, reason: " . socket_strerror($ret));
}
if (($ret = socket_listen($this->masterSocket, 5)) < 0) {
$this->logger->log("[SocketServer] "."socket_listen() failed, reason: " . socket_strerror($ret));
}
}
private function parseRequest($socket, $data)
{
if(substr($data,0, 22) == "<policy-file-request/>")
{
echo "POLICY FILE REQUEST\n";
$crossFile = file("crossdomain.xml");
$crossFile = join('',$crossFile);
$this->sendMessage(array($socket),$crossFile);
return;
}
else
{
//Here you handle the request
}
}
public function sendMessage( $message)
{
$message .= "\0";
foreach($this->currentSockets as $socket)
{
if($socket === NULL)
continue;
socket_write($socket, $message, strlen($message));
socket_getpeername($socket, $newClientAddress);
$this->logger->log("[SocketServer] Wrote : ".$message." to ". $newClientAddress);
}
}
public function closeConnection()
{
foreach($this->currentSockets as $socket)
{
if ($socket != $this->masterSocket) {
socket_getpeername($socket, $newClientAddress);
$this->logger->log("[SocketServer] "."REMOVING CLIENT ". $newClientAddress);
socket_close($socket);
}
}
$this->logger->close();
exit;
}
private function listenToSockets()
{
while (true) {
$changed_sockets = $this->currentSockets;
$num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL);
foreach($changed_sockets as $socket)
{
if ($socket == $this->masterSocket) {
if (($client = socket_accept($this->masterSocket)) < 0) {
$this->logger->log("[SocketServer] "."socket_accept() failed: reason: " . socket_strerror($socket));
continue;
} else {
// NEW CLIENT HAS CONNECTED
$this->currentSockets[] = $client;
socket_getpeername($client, $newClientAddress);
$this->logger->log("[SocketServer] "."NEW CLIENT ".$client." [IP: ".$newClientAddress."]");
}
} else {
$bytes = socket_recv($socket, $buffer, 4096, 0);
if ($bytes == 0) {
// CLIENT HAS DISCONNECTED
socket_getpeername($client, $newClientAddress);
$this->logger->log("[SocketServer] "."REMOVING CLIENT ". $newClientAddress);
$index = array_search($socket, $this->currentSockets);
// Remove Socket from List
unset($this->currentSockets[$index]);
socket_close($socket);
//exit;
}else{
// CLIENT HAS SENT DATA
$this->parseRequest($socket, $buffer);
}
}
}
}
}
}
?>
La classe Logger (en Singleton comme on ne veut qu'un seul Log), on ecrit dans un txt, mais ca peut se changer facilement:
Code PHP :
<?php
class Logger
{
private static $instance;
var $Fnm;
var $inF;
var $ptr;
public static function getInstance()
{
if(!isset($instance))
$instance = new Logger();
return $instance;
}
function __construct()
{
$this->Fnm = 'log.txt';
$this->inF = fopen($this->Fnm, 'w');
$this->ptr = ftell($this->inF);
}
function log($message)
{
$message = "[".date('Y-m-d at h:i:s')."] ".$message."<br/>\n";
fputs($this->inF, $message);
}
function close()
{
fclose($this->inF);
}
}
?>