У меня проблема с сокетом, когда я отправляю данные клиенту, другие клиенты отключаются, функция 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.