我有多个TCP服务器,它们以相同的格式提供输出流。我正在尝试用PHP编写一个客户端,该客户端将连接到每个客户端,并接受它们流式传输到它的数据。我的意图是将这些多个流合并为一个流,以供以后处理。
我已经编写了一个TCP服务器,在此之前主套接字接受连接,而在新客户端连接时,这将创建一个新套接字。将此新套接字添加到套接字数组中,然后使用sockect_select检测要读取的套接字。
我想采用类似的方法,尽管我知道我没有主套接字,我需要做的是为每个客户端-服务器连接创建一个套接字。
我编写的代码允许我构建此套接字列表,但是当我运行它时,代码告诉我套接字已更改,但此时我被卡住了。
我怎么知道要从哪个套接字读取?
$client = new Client();
// start the server
$client->connect('1.2.3.4', 50000);
$client->connect('5.6.7.8', 50001);
public function connect($ip, $port) {
// Connect to remote server
try{
// Create socket
if ($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) {
$this->log("Socket created");
} else {
$this->log("Error creating socket");
}
// Connect to server
if (socket_connect($socket, $ip, $port)){
$this->log("Socket connected to $ip:$port");
$this->sockets[]=$socket;
$this->onConnected();
} else {
$this->log("Error connecting to server");
}
} catch(Exception $e){
$this->log("Error: " . $e->getMessage());
}
}
public function onConnected() {
foreach ($this->sockets as $socket) {
socket_set_nonblock($socket);
}
// Add the socket that we're monitoring to an array
$streams=$this->sockets;
$write=null;
$except=null;
// Look for data on the socket
while (socket_select($streams, $write, $except, 0, 0) !== FALSE) {
echo ("Socket changed");
// The following code doesn't read from the socket
if (in_array($this->sockets, $streams)) {
// Read up to 8K of data into the buffer
while (@socket_recv($this->sockets, $buffer, 8192, 0)) {
echo ("LINE: " . $buffer);
}
}
$streams=$this->sockets;
}
}
我希望看到的是来自每个服务器输出的数据行,但我只是看到很多“套接字已更改”
那么,如何确定哪个套接字已更改,以便可以从中读取?
答案 0 :(得分:0)
如果您阅读socket_select()上的PHP手册,则会显示:
警告:在退出时,将修改阵列以指示实际更改了哪个套接字资源的状态。
还有:
成功时,socket_select()返回套接字资源的数量 包含在修改后的数组中,如果超时则可能为零 在发生任何有趣的事情之前就过期了。
因此$streams
中剩下的所有内容(即您的套接字)都是已更改的套接字。
知道这一点,下面的代码毫无意义:
if (in_array($this->sockets, $streams)) {
因为$this->sockets
包含所有套接字,而$streams
仅包含已更改的套接字。换句话说,它将始终为false
。您可以做的是:
public function onConnected() {
// Add the socket that we're monitoring to an array
$streams = $this->sockets;
$write = null;
$except = null;
// Look for data on the socket
while (socket_select($streams, $write, $except, 0, 0) !== FALSE) {
echo ("Socket changed");
// The following code does read from the sockets that have changed
foreach ($streams as $stream) {
while (socket_recv($stream, $buffer, 8192, 0)) {
echo ("LINE: " . $buffer);
}
}
// Look at all streams again
$streams = $this->sockets;
}
// The following code does read from the sockets that have changed
foreach ($streams as $stream) {
while (socket_recv($stream, $buffer, 8192, 0)) {
echo ("LINE: " . $buffer);
}
}
}
这应该从更改后的套接字中读取,假设其余代码可以正常工作。