отримання причини, чому веб-сокети закриваються закритим кодом 1006


92

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

У мене є

sok.onerror=function (evt) 
     {//since there is an error, sockets will close so...
       sok.onclose=function(e){
           console.log("WebSocket Error: " , e);}

Код завжди 1006, а причина завжди "". Але я хочу сказати різні причини закриття.

Наприклад, рядок comand дає причину помилки: "Ви не можете видалити це, тому що база даних не дозволить вам". Але на консолі Chrome причина все-таки "".

Будь-який інший спосіб розрізнити різні причини закриття?


Я думаю, це через те, як сервер обробляє підключені / відключені події. Я не можу сказати точно, але закриття з'єднання потрібно правильно обробляти на сервері, також з кодом. Спробуйте перевизначити вбудовані методи підключення / відключення на сервері і подивіться. Я лише припускаю, що ви закриваєте його, але сервер не закривається належним чином і тому не передає належну закриту відповідь.
Майкл Пакетт II,

Відповіді:


124

Закрити код1006 - це спеціальний код, який означає, що зв’язок був аномально (локально) закритий реалізацією браузера.

Якщо клієнт вашого браузера повідомляє про закриття коду 1006, то вам слід переглянути websocket.onerror(evt)детальну інформацію про подію.

Однак Chrome рідко повідомляє про будь-які 1006причини близького коду стороні Javascript. Ймовірно, це пов’язано з правилами безпеки клієнта в специфікації WebSocket, щоб запобігти зловживанню WebSocket. (наприклад, використовувати його для пошуку відкритих портів на цільовому сервері або для створення безлічі з'єднань для атаки відмови в обслуговуванні).

Зверніть увагу, що Chrome часто повідомляє про закритий код, 1006якщо під час оновлення HTTP до Websocket виникає помилка (це крок до технічного «підключення» WebSocket). З таких причин, як погана автентифікація чи авторизація, або неправильне використання протоколу (наприклад, запит на підпротокол, але сам сервер не підтримує цей самий підпротокол), або навіть спроба розмови з місцем сервера, яке не є WebSocket ( наприклад, спроба підключитися до ws://images.google.com/)

Принципово, якщо ви бачите закритий код 1006, у вас є дуже низький рівень помилки з самим WebSocket (подібно до "Неможливо відкрити файл" або "Помилка сокета"), яка насправді не призначена для користувача, оскільки вказує на проблему низького рівня з вашим кодом та реалізацією. Виправте свої проблеми низького рівня, і тоді, коли ви під’єднаєтесь, ви зможете включити більш розумні коди помилок. Ви можете досягти цього з точки зору масштабу або суворості у своєму проекті. Приклад: інформація та рівень попередження є частиною конкретного протоколу вашого проекту і не спричиняють припинення з’єднання. Зі серйозними або фатальними повідомленнями звітність також використовується за допомогою протоколу вашого проекту, щоб передати стільки деталей, скільки вам потрібно, а потім закриття з'єднання, використовуючи обмежені можливості WebSocket.

Майте на увазі, що коди закриття WebSocket дуже суворо визначені, і фраза / повідомлення з близькою причиною не може перевищувати 123 символи (це навмисне обмеження WebSocket).

Але не все втрачено, якщо ви просто хочете отримати цю інформацію з причин налагодження, деталі закриття та її основна причина часто повідомляються з достатньою кількістю деталей у консолі Javascript Chrome.


4
Йоакиме, дякую, дуже детальний ансер. Якщо я використовую sok.onerror=function (evt) {console.log(evt);}деталі не так вже й багато. Навіть ні reasonчи щось. Отже, варіантів немає взагалі? Я просто показую користувачеві. something is wrong, or not connencted?Не так зручно, було б непогано, якщо користувач бачить "Ви не можете видалити, причина обмежень бази даних". Будь-які варіанти? Дякую
slevin

sok.oncloseНатомість слід використовувати які тригери close event, він має reasonі codeв них
Іхаб Хаттаб

@IhabKhattab, що стосується конкретного коду, а також коли відбувається закриття. наявність sok.oncloseбуде працювати на багатьох шляхах, але не на всіх. Особливо поганий протокол, погані помилки рукостискання (наприклад, деякі умови, які можуть спричинити близький код 1006). Чи зміниться це в майбутньому? Ймовірно. Але коли ця відповідь була написана, це було правдою.
Йоакім Ердфельт

@JoakimErdfelt вибачте, я відповідав на запитання @slevin про те, що він не reasonповернувся, коли він використовував, onerrorя вказував, що ці властивості code& reasonспецифічні для closeподії, а не errorподії. так що було б краще для його використовувати oncloseзамість цього, я що - то відсутня?
Іхаб Хаттаб,

@IhabKhattab так, оскільки його запитання було конкретним щодо коду помилки, 1006який має особливе значення, та спеціальної обробки в специфікації websocket та api веб-сокета javascript. Рядок / повідомлення про причину за певних 1006умов спеціально та навмисно не відображаються ніде в API. (як зазначено у відповіді). Це не помилка в API, вона просто стосується різних специфікацій та їх занепокоєння щодо зловживання веб-сокетом для інших цілей.
Йоакім Ердфельт

16

У моєму і, можливо, випадку @BIOHAZARD це було nginx proxy timeout. За замовчуванням це 60сек без активності в сокеті

Я змінив його на 24 години, nginxі це вирішило проблему

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

Дякую за це! Це причина помилки 1006 у моєму випадку.
Стів Ханов,

11

Схоже, це так, коли Chrome не відповідає стандарту WebSocket. Коли сервер ініціює закриття та надсилає клієнту фрейм закриття, Chrome вважає це помилкою і повідомляє про це стороні JS з кодом 1006 і без повідомлення про причину. У моїх тестах Chrome ніколи не реагує на ініційовані сервером закриті кадри (закритий код 1000), припускаючи, що код 1006, ймовірно, означає, що Chrome повідомляє про власну внутрішню помилку.

PS Firefox v57.00 правильно обробляє цю справу та успішно доставляє повідомлення про причину сервера на сторону JS.


3

Думав, це може бути корисно для інших. Знати регулярний вираз корисно, діти. Залишайтеся в школі.

Редагувати: перетворив це на зручну функцію денді!

let specificStatusCodeMappings = {
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
};

function getStatusCodeString(code) {
    if (code >= 0 && code <= 999) {
        return '(Unused)';
    } else if (code >= 1016) {
        if (code <= 1999) {
            return '(For WebSocket standard)';
        } else if (code <= 2999) {
            return '(For WebSocket extensions)';
        } else if (code <= 3999) {
            return '(For libraries and frameworks)';
        } else if (code <= 4999) {
            return '(For applications)';
        }
    }
    if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
        return specificStatusCodeMappings[code];
    }
    return '(Unknown)';
}

Використання:

getStatusCodeString(1006); //'Abnormal Closure'

{
    '0-999': '(Unused)',
    '1016-1999': '(For WebSocket standard)',
    '2000-2999': '(For WebSocket extensions)',
    '3000-3999': '(For libraries and frameworks)',
    '4000-4999': '(For applications)'
}

{
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
}

Джерело (з незначними редагуваннями для стислості): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes


1

У мене виникла помилка під час використання Chrome як клієнта та golang gorilla websocket як сервера під проксі nginx

І надсилання лише декількох повідомлень "ping" із сервера на клієнт кожні х секунд вирішеної проблеми


0

Це може бути ваша URL-адреса веб-розетки, яку ви використовуєте на пристрої, не однакова (Ви натискаєте іншу URL-адресу веб-розетки від android / iphonedevice)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.