получение причины, по которой веб-сокеты закрываются с кодом закрытия 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 и причина всегда "". Но я хочу выделить разные заключительные причины.

Например, в командной строке указывается причина ошибки: «вы не можете удалить это, потому что база данных не позволит вам». Но на консоли Chrome причина по-прежнему "".

Есть ли другой способ отличить разные причины закрытия?

Slevin
источник
Я думаю, это связано с тем, как сервер обрабатывает подключенные / отключенные события. Я не могу сказать точно, но закрытие соединения необходимо правильно обрабатывать на сервере также с помощью кода. Попробуйте переопределить встроенные методы On Connected / Disconnected на сервере и посмотрите. Мое предположение заключается только в том, что вы закрываете его, но сервер не закрывается должным образом и, следовательно, не передает правильный закрытый ответ.
Майкл Пакетт 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который имеет особое значение, и специальной обработке в спецификации веб-сокета и javascript websocket api. Строка / сообщение причины при некоторых 1006условиях специально и намеренно не отображаются нигде в API. (как указано в ответе). Это не ошибка API, это просто решение различных спецификаций и их озабоченность по поводу злоупотребления веб-сокетом для целей, не связанных с веб-сокетом.
Йоаким Эрдфельт
16

В моем случае и, возможно, в случае @BIOHAZARD это было так nginx proxy timeout. По умолчанию это 60sec без активности в сокете

Я изменил его на 24 часа nginxи решил проблему.

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
MixerOID
источник
Спасибо за это! Это причина ошибки 1006 в моем случае.
Стив Ханов,
11

Похоже, это тот случай, когда Chrome не совместим со стандартом WebSocket. Когда сервер инициирует закрытие и отправляет клиенту кадр закрытия, Chrome считает это ошибкой и сообщает об этом стороне JS с кодом 1006 без сообщения о причине. В моих тестах Chrome никогда не реагирует на инициированные сервером кадры закрытия (код закрытия 1000), предполагая, что код 1006, вероятно, означает, что Chrome сообщает о собственной внутренней ошибке.

PS Firefox v57.00 правильно обрабатывает этот случай и успешно доставляет сообщение о причине сервера на сторону JS.

user10663464
источник
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" сообщения от сервера к клиенту каждые x секунд решает проблему.

БИОЛОГИЧЕСКАЯ ОПАСНОСТЬ
источник
0

Это может быть ваш URL-адрес веб-сокета, который вы используете на устройстве, не тот же (вы нажимаете другой URL-адрес веб-сокета из android / iphonedevice)

Анкуш Саху
источник