Websocket.close() вызывается, но не закрывается, не отправляет закрытый кадрPhp

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Websocket.close() вызывается, но не закрывается, не отправляет закрытый кадр

Сообщение Anonymous »

У меня есть веб-приложение для чата на HTML/JavaScript, использующее WebSockets. Я также создал простой сервер сокетов Ubuntu Linux/Apache2/PHP, предназначенный для WebSockets, используя ванильный PHP без сторонних библиотек. Я использую модуль Apache2 proxy_wstunnel для передачи трафика WebSocket на мой сервер. Я не могу использовать на стороне сервера ничего, кроме стандартного PHP (это означает, что я не хочу использовать сторонние расширения или библиотеки из соображений безопасности).
WebSocket настроен следующим образом:
let ws = null;

// [...]

// set up websocket stuff
ws = new WebSocket('wss://redacted.com/ws/');

Типичный текстовый фрейм отправляется следующим образом:
let jOut = {act: 'u', typ: '+', usr: uname, grp: gname, tstamp: nowTimestamp()};

ws.send(JSON.stringify(jOut));

Когда сервер сокетов PHP работает, я могу успешно подключиться к веб-приложению и без проблем отправлять текстовые фреймы. По завершении я вызываю следующую команду, чтобы закрыть WebSocket:
console.log('At ws.close()');

if (ws.readyState === WebSocket.OPEN) {
console.log('WebSocket is open, attempting to close');
ws.close();
} else {
console.log('WebSocket isn\'t open, not closing');
}

На консоли отображается сообщение «At ws.close()», но после него ничего не отображается. Примерно через десять секунд я получаю на консоли ошибку WebSocket (без какой-либо полезной информации), а также уведомление о том, что WebSocket закрылся некорректно с кодом 1006.
При просмотре инструментов разработчика в Firefox, Safari и Brave текстовые фреймы (код операции 0x1) отображаются успешно отправленными, но я никогда не вижу отправляемого закрывающего кадра (код операции 0x8).
На стороне сервера для при отладке я запускаю свой сервер сокетов PHP в командной строке. Я настроил несколько выводов отладки на стандартный вывод и вижу только код операции 0x1, полученный от клиентов чата веб-приложений (работающих в Firefox, Safari или Brave). Я никогда не вижу закрывающий кадр (0x8) или какой-либо другой код операции.
Сервер сокетов PHP настроен следующим образом:
// create socket server
$server = stream_socket_server("tcp://127.0.0.1:8088", $errno, $errstr);

Я использую это для ожидания данных клиента:
$read = $clients; // copy $clients[] to $read[][
$read[] = $server; // add $server to $read[]
$except = null; // unused but variable needed for stream_select
$write = null; // unused but variable needed for stream_select

// wait for a stream to have data or time out after 200 ms
if (stream_select($read, $write, $except, 0, 200000))
{
// [...]
}

Вот строки чтения и отладки клиентского сокета на сервере сокетов PHP:
// this is a client, so read their data
$data = fread($sock, 8192);

if ($data === '') {
// nothing available right now, but not EOF
continue;
}

if ($data !== '' && $data !== false)
{
fwrite(STDOUT, "Received frame: " . bin2hex($data) . "\n"); // Full frame in hex
fwrite(STDOUT, "Received hex opcode: " . dechex(ord($data[0]) & 15) . "\n");
}

Когда клиент веб-приложения вошел в систему и после подтверждения WebSocket веб-клиент отправляет на сервер несколько текстовых фреймов. Эти текстовые фреймы успешно передаются другим подключенным клиентам (код не показан). После этого я пробую ws.close() в веб-клиенте, но получаю только следующий отладочный результат:
Received frame: 81cad2260131a90460[...]
Received hex opcode: 1

Received frame: 81da632b9f561809fe[...]
Received hex opcode: 1

Received frame: 81ca90cdaafdebefcb[...]
Received hex opcode: 1

Код операции 0x8 никогда не виден, а веб-клиент истекает по тайм-ауту и ​​выводит ранее упомянутую ошибку и код закрытия 1006.
Я провел обширный поиск в Интернете и обошелся с двумя разными механизмами искусственного интеллекта, но это было непродуктивно. Мне интересно, есть ли у кого-нибудь идеи, почему ws.close() не выполняется на веб-клиентах, почему они не отправляют закрывающий кадр на сервер, в то время как текстовые кадры работают нормально (не кажется проблемой сети).

После применения изменений в коде close(), предложенном @VC.One, он фактически попадает в метод close() сейчас, но я все еще не получаю код операции 0x8 на сервере, и через семь-десять секунд я все еще получаю код закрытия 1006.
Внесенные изменения:
-- Source - https://stackoverflow.com/a/79844803
-- Posted by VC.One
-- Retrieved 2025-12-12, License - CC BY-SA 4.0

console.log('At ws.close()');
console.log('ws readyState is: ' + ws.readyState);

//# a "readyState" of 1 means WebSocket.OPEN
if (ws.readyState === 1) {
console.log('WebSocket is open, attempting to close');
ws.close();
} else {
console.log('WebSocket isn\'t open, not closing');
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... lose-frame
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»