Поддерживать сокет после чтения клиентов - PullRequest
0 голосов
/ 10 ноября 2019

У меня проблема с сокетом, когда я отправляю данные клиенту, другие клиенты отключаются, функция socket_read возвращает false, и только клиент с данными, которые я отправляю, не отключается, и я не вижу, как решить проблему, потому что клиенты должнывсегда подключайтесь нормально.

Я хочу убедиться, что клиенты отключаются, только если он больше не общается с сервером или если он был отключен.

Извините за мой плохой английский и спасибо за чтение.

С уважением, Николас

<?php

class Server
{

    public $id = [];
    public $all = [];

    public $mastersock;

    public $n = 0;

    public $close = false;
    public $timeout = 0;


    public function __construct()
    {
        set_time_limit(0);
    }

    /**
     * @return array
     */
    public function getClients(): array
    {
        return $this->id;
    }


    /**
     * @param array $id
     */
    public function addClient(array $id)
    {
        $this->id[] = $id;
    }

    /**
     * @param int $id
     */
    public function disconnectClient(int $id)
    {
        if (isset($this->getClients()[$id])) {
            $socket = $this->getClients()[$id];
            socket_close($socket);
            $i = array_search($socket, $this->all);
            unset($this->all[$i]);
            unset($this->id[$id]);
            --$this->n;
        }
    }

    /**
     * @return array
     */
    public function getAll(): array
    {
        return $this->all;
    }


    /**
     * @param $socket
     */
    public function setAll($socket): void
    {
        $this->all[] = $socket;
    }


    /*
     * You need to run this function first for launch the Server and for communating with the clients.
     */
    public function connect()
    {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
        socket_bind($socket, '127.0.0.1', 7000);
        socket_listen($socket, 5);
        socket_set_nonblock($socket);


        if ($socket) {
            Logger::info(Logger::getLocale() . Color::COLOR_GREEN . "You are now connected on Server.");
            Logger::updateTitle(count($this->getClients()));
            $this->setAll($socket);
            $this->insertClient($socket);
        } else {
            Logger::info(Logger::getLocale() . Color::COLOR_RED . "Impossible to connect to the Server.");
            socket_close($socket);
            socket_shutdown($socket);
        }
    }


    /**
     * @param $socket
     */
    public function insertClient($socket)
    {
        while (true) {
            usleep(500); //500 milliseconds.

            $r = $w = $e = $this->all;
            $result = socket_select($r, $w, $e, 0);

            if ($result > 0) {
                foreach ($r as $sock) {
                    if ($sock == $socket) {
                        $this->setAll($newsock = socket_accept($socket)); //add a client on the socket_list.
                        if ($socket) {
                            ++$this->n;
                            if (!isset($this->getClients()[$this->n])) {
                                socket_set_nonblock($newsock);
                                socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
                                $this->id[$this->n] = $newsock;
                                Logger::info(Logger::getLocale() . Color::COLOR_YELLOW . "Connected: Client: #" . $this->n);
                                Logger::info(Logger::getLocale() . Color::COLOR_GREEN . count($this->getClients()) . " Clients Online(s)");
                                Logger::updateTitle(count($this->getClients()));

                            }
                        }
                    } else {
                        $response = $this->response();
                        if (!empty($response)) { //waiting for a response from a client and communating information with other clients.
                            foreach ($response as $id => $buff) {
                                $this->sendToAll($buff);//send buff to all clients.
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * @param $data
     */
    public function sendToAll($data)
    {
        foreach ($this->getClients() as $id => $client) {
            @socket_write($client, $data, strlen($data));
        }
    }

    public function response()
    {
        $read = [];
        foreach ($this->getClients() as $id => $client) {
            socket_set_nonblock($client);
            $res = @socket_read($client, 1024);
            if (!$res) { //An empty or false bool information count as a disconnected client
                Logger::info(Logger::getLocale() . Color::COLOR_RED . "Disconnected: Client: #" . $id . " timeout.");
                $this->disconnectClient($id);
                Logger::info(Logger::getLocale() . Color::COLOR_GREEN . count($this->getClients()) . " Clients Online(s)");
                Logger::updateTitle(count($this->getClients()));
                continue;
            }

            if ($res) {
                Logger::info(Logger::getLocale() . Color::COLOR_GREEN . $res); //Server will receive information from the clients
            }
            $read[$id] = $res;
        }
        return $read;
    }
}

$server = new Server();
$server->connect();```

Output: false from socket_read.
...