PHP套接字客户端连接到多个远程服务器以合并输出

时间:2019-06-15 07:58:04

标签: php sockets client

我有多个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;
    }
}

我希望看到的是来自每个服务器输出的数据行,但我只是看到很多“套接字已更改”

那么,如何确定哪个套接字已更改,以便可以从中读取?

1 个答案:

答案 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);
        }
    }
}

这应该从更改后的套接字中读取,假设其余代码可以正常工作。