2013-12-11 31 views
1

我想要實現的是一個套接字服務器,它將一些數據廣播給所有連接的對等體。這是服務器循環的代碼:PHP多連接套接字(廣播問題)

while(TRUE) { 
    $read = array(); 

    $read[] = $socket; 

    for($i = 0; $i < $max_clients; $i++) { 
     if($client_sockets[$i] != NULL) { 
      $read[$i+1] = $client_sockets[$i]; 
     } 
    } 

    #This is broadcasting loop 
    foreach($client_sockets as $send_sock) 
    { 
     socket_write($send_sock, "broadcasting".PHP_EOL); 
    } 

    if(socket_select($read, $write, $except, NULL) === FALSE) { 
     $errorcode = socket_last_error(); 
     $errormsg = socket_strerror($errorcode); 
     die("Could not listen on socket : [$errorcode] $errormsg \n"); 
    } 

    if(in_array($socket, $read)) { 
     for($i = 0; $i < $max_clients; $i++) { 
      if($client_sockets[$i] == NULL) { 
       $client_sockets[$i] = socket_accept($socket); 

       if(socket_getpeername($client_sockets[$i], $client_address, $client_port)) { 
        echo "Client $client_address : $client_port is now connected to us. \n"; 
       } 

       $message = "Connected to php socket server".PHP_EOL; 
       socket_write($client_sockets[$i], $message); 
       break; 
      } 
     } 
    } 
} 

此代碼工作正常,接受多個連接和廣播數據,除了一個時刻:循環開始後,才通過telnet從任何連接的客戶端類型的任何輸入。我知道這是因爲socket_select等待此輸入​​,但我不知道如何在客戶端連接後開始播放。

欣賞這方面的任何幫助,因爲我覺得我在某個地方是非常錯誤的。

+0

你應該發佈你的更新作爲答案並接受你自己 –

回答

0

Selfown回答

問題確實是socket_select($read, $write, $except, NULL);而實際上並不是一個問題。最後NULL參數啓動無盡塊,等待客戶端響應;爲了使腳本正常工作,我已經改變了這個超時,所以看起來是這樣的:socket_select($read, $write, $except, 0, 500000)。但是,在客戶端,參數應該設置爲NULL不是0!),因此腳本在等待服務器廣播消息時保持空閒狀態。

我也發現,這種阻止行爲類似於socket_read()socket_write()函數,默認情況下是無止境的;改變它,使用socket_set_option

socket_set_option($master_socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 1000)); 
socket_set_option($master_socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 0, "usec" => 1000)); 

和1000微秒低至我能得到。

其實,我已經更新了投票的人的答案;但我希望解決方案無論如何都會有用。