2009-06-24 10 views
1

J'ai créé un PHP Socket Server avec le mode PHP_NORMAL_READ. Ainsi, un message au serveur est lu lorsqu'il se termine par \ n ou \ r. Je l'ai essayé en me connectant au serveur avec plusieurs instances telnet, et ça marche très bien. Cependant, lorsque je me connecte au serveur avec 1 application flash et 1 application telnet (je commence d'abord le flash), le flash semble bloquer le serveur - le serveur se bloque quelque part et ne reçoit plus de données par exemple le client telnet. Étant donné que n'importe qui peut coder un client Flash, il doit être fixé côté serveur. Le code du serveur:Pourquoi mon serveur PHP Socket Server est-il suspendu?

<?php 
// config 
$timelimit = 60; // amount of seconds the server should run for, 0 = run indefintely 
$port = 9000; // the port to listen on 
$address = $_SERVER['SERVER_ADDR']; // the server's external IP 
$backlog = SOMAXCONN; // the maximum of backlog incoming connections that will be queued for processing 

// configure custom PHP settings 
error_reporting(1); // report all errors 
ini_set('display_errors', 1); // display all errors 
set_time_limit($timelimit); // timeout after x seconds 
ob_implicit_flush(); // results in a flush operation after every output call 

//create master IPv4 based TCP socket 
if (!($master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) die("Could not create master socket, error: ".socket_strerror(socket_last_error())); 

// set socket options (local addresses can be reused) 
if (!socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1)) die("Could not set socket options, error: ".socket_strerror(socket_last_error())); 

// bind to socket server 
if (!socket_bind($master, $address, $port)) die("Could not bind to socket server, error: ".socket_strerror(socket_last_error())); 

// start listening 
if (!socket_listen($master, $backlog)) die("Could not start listening to socket, error: ".socket_strerror(socket_last_error())); 

//display startup information 
echo "[".date('Y-m-d H:i:s')."] SERVER CREATED (MAXCONN: ".SOMAXCONN.").\n"; //max connections is a kernel variable and can be adjusted with sysctl 
echo "[".date('Y-m-d H:i:s')."] Listening on ".$address.":".$port.".\n"; 
$time = time(); //set startup timestamp 

// init read sockets array 
$read_sockets = array($master); 

// continuously handle incoming socket messages, or close if time limit has been reached 
while ((!$timelimit) or (time() - $time < $timelimit)) { 
    $changed_sockets = $read_sockets; 
    socket_select($changed_sockets, $write = null, $except = null, null); 
    foreach($changed_sockets as $socket) { 
     if ($socket == $master) { 
      if (($client = socket_accept($master)) < 0) { 
       continue; 
      } else { 
       array_push($read_sockets, $client); 
      } 
     } else { 
      $data = @socket_read($socket, 1024, PHP_NORMAL_READ); //read a maximum of 1024 bytes until a new line has been sent 
      if ($data === false) { //the client disconnected 
       $index = array_search($socket, $read_sockets); 
       unset($read_sockets[$index]); 
       socket_close($socket); 
      } elseif ($data = trim($data)) { //remove whitespace and continue only if the message is not empty 
       echo "we received: ".$data."\n\n"; 
       //handleData($data, $socket); 
      } 
     } 
    } 
} 
socket_close($master); //close the socket 
echo "[".date('Y-m-d H:i:s')."] SERVER CLOSED.\n"; 

//function to write to the flash client 
function flash_write($socket, $msg) { 
    socket_write($socket, $msg.chr(0x0)); 
} 
?> 

Est-ce que quelqu'un sait ce que cela peut causer? J'ai essayé de changer le timeout sur le socket_select de none à 0 (retour instantané), mais cela n'a pas semblé changer n'importe quoi. Une chose pour vous aider à déboguer: error_reporting (1) ne permet pas l'affichage de toutes les erreurs.

Répondre

2

Pourriez-vous publier la source du client Flash? Cela montrerait quel est le problème? Etes-vous sûr que la dernière chose que vous envoyez depuis le client flash est un \ n?

Sinon le serveur bloquerait sur socket_read() car le socket client flash peut être lu sans bloquer (déclenché socket_select()), mais n'envoie pas la fin \ n.

+1

@bucabay a la bonne réponse. socket_select() se déclenchera lorsque les données seront prêtes sur le socket, mais ne garantira pas que les données contiennent le newline terminal que socket_read ($ socket, 1024, PHP_NORMAL_READ) attend. Si vous souhaitez protéger DoS contre un client malveillant (ou simplement négligent), vous devrez lire en mode binaire et rechercher vous-même la nouvelle ligne. – bd808

+0

Je vais essayer le mode binaire. Cependant, j'ai dit que la suppression du délai d'attente socket_select n'a pas aidé. – Tom

+0

Deuxième remarque: je pense que socket_select n'est pas le problème (testé aussi) car il cherche des entrées de tous les clients. Donc, si le client n ° 2 dit quelque chose mais que le client n ° 1 ne le fait pas, il continuera malgré tout. Cela ne continuera pas si 0 clients font quelque chose, mais c'est une bonne chose. – Tom

Questions connexes