我想要实现的是一个套接字服务器,它向所有连接的对等体广播一些数据。这是服务器循环的代码:
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)
自我回答
问题确实在socket_select($read, $write, $except, NULL)
;而不是一个问题。最后NULL
参数开始无休止,等待客户响应;为了使脚本正常工作,我已经更改了这个超时,所以它看起来像这样:socket_select($read, $write, $except, 0, 500000)
。但是,在客户端,参数应设置为NULL
( NOT 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微秒是我能得到的最低值。
实际上,我已经为投票的人更新了答案;但我希望这个解决方案无论如何都会有用。