2009-06-24 4 views
1

PHP_NORMAL_READモードでPHPソケットサーバーを作成しました。したがって、\ nまたは\ rで終わると、サーバーへのメッセージが読み込まれます。私は複数のtelnetインスタンスを使用してサーバーに接続してみましたが、うまくいきました。私のPHPソケットサーバがぶら下がっているのはなぜですか?

しかし、1つのフラッシュアプ​​リケーションと1つのTelnetアプリケーションでサーバーに接続すると、フラッシュがサーバーをハングアップさせるように見えます。サーバーはどこかにつかれてデータを受信して​​いません例えば、テルネットクライアント。

誰でもフラッシュクライアントをコードできるため、これはサーバー側で固定する必要があります。サーバーのコード:

<?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)); 
} 
?> 

誰でもこの原因が考えられますか? socket_selectのタイムアウトをnoneから0(瞬時に戻る)に変更しようとしましたが、何も変更されていないようです。

答えて

2

フラッシュクライアントのソースを投稿できますか?それは問題が何であるかを示します。

最後にフラッシュクライアントから送信するものは\ nですか?

そうしないと、サーバーはブロックしないで(ソケットsocket_select()を起動して)フラッシュクライアントソケットを読み取ることができるため、socket_read()をブロックしますが、終了\ nは送信しません。

+1

@bucabayには正しい答えがあります。 socket_select()は、データがソケット上で準備されているときに起動しますが、データにsocket_read($ socket、1024、PHP_NORMAL_READ)が待機している端末改行を含んでいるとは限りません。悪意のある(または怠慢な)クライアントによってDoSから保護したい場合は、バイナリモードで読んで改行を探す必要があります。 – bd808

+0

私はバイナリモードを試みます。しかし、私はsocket_selectタイムアウトを削除しても役に立たなかったと言いました。 – Tom

+0

第2の注意:socket_selectはすべてのクライアントからの入力を探しているので問題ではないと思う。したがって、クライアント#2が何かを言うがクライアント#1はそうでないと言うと、それは関係なく続行する。 0人のクライアントが何かをしてもそれは続かないでしょうが、それは良いことです。 – Tom

関連する問題