PHP-сокет-клиент для подключения к нескольким удаленным серверам для объединения выходных данных - PullRequest
0 голосов
/ 15 июня 2019

У меня есть несколько 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 голосов
/ 15 июня 2019

Если вы читаете руководство PHP по socket_select () , оно говорит:

Предупреждение При выходе массивы модифицируются, чтобы указать, какой ресурс сокета фактически изменил состояние.

А также:

В случае успеха 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);
        }
    }
}

Это следует читать из измененных сокетов, предполагая, что остальная часть кода работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...