uzyskanie powodu, dla którego websockets zostały zamknięte kodem zamknięcia 1006


92

Chciałbym poznać powód zamknięcia websockets, żeby pokazać użytkownikowi właściwą wiadomość.

mam

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

Kod to zawsze 1006, a powodem jest zawsze „”. Ale chcę rozróżnić różne powody zamknięcia.

Na przykład wiersz poleceń podaje przyczynę błędu: „nie można tego usunąć, ponieważ baza danych na to nie pozwala”. Ale na konsoli Chrome przyczyną jest nadal „”.

Czy jest jakiś inny sposób na odróżnienie różnych powodów zamknięcia?


Myślę, że jest to spowodowane tym, jak serwer obsługuje zdarzenia związane / rozłączone. Nie mogę powiedzieć na pewno, ale zamknięcie połączenia musi zostać poprawnie obsłużone na serwerze również z kodem. Spróbuj zastąpić wbudowane metody On Connected / Disconnected na serwerze i zobacz. Zakładam tylko, że zamykasz go, ale serwer nie zamyka się poprawnie i dlatego nie przekazuje prawidłowej odpowiedzi zamkniętej.
Michael Puckett II

Odpowiedzi:


124

Kod zamknięcia1006 to specjalny kod, który oznacza, że ​​połączenie zostało zamknięte nieprawidłowo (lokalnie) przez implementację przeglądarki.

Jeśli klient przeglądarki zgłasza kod zamknięcia 1006, należy przyjrzeć się websocket.onerror(evt)zdarzeniu, aby uzyskać szczegółowe informacje.

Jednak Chrome rzadko zgłasza 1006przyczyny zamknięcia kodu po stronie JavaScript. Jest to prawdopodobnie spowodowane regułami bezpieczeństwa klienta w specyfikacji protokołu WebSocket, aby zapobiec nadużywaniu protokołu WebSocket. (np. używanie go do skanowania w poszukiwaniu otwartych portów na serwerze docelowym lub do generowania wielu połączeń w przypadku ataku typu „odmowa usługi”).

Pamiętaj, że Chrome często zgłasza kod zamknięcia, 1006jeśli wystąpi błąd podczas uaktualniania HTTP do Websocket (jest to krok przed technicznym „połączeniem” WebSocket). Z powodów takich jak złe uwierzytelnienie lub autoryzacja lub złe użycie protokołu (na przykład żądanie podprotokołu, ale sam serwer nie obsługuje tego samego podprotokołu), a nawet próba nawiązania połączenia z lokalizacją serwera, która nie jest protokołem WebSocket ( takie jak próba połączenia się ws://images.google.com/)

Zasadniczo, jeśli widzisz kod zamknięcia 1006, masz bardzo niski poziom błędu z samym WebSocket (podobny do „Unable to Open File” lub „Socket Error”), który nie jest przeznaczony dla użytkownika, ponieważ wskazuje na problem niskiego poziomu swoim kodem i implementacją. Rozwiąż problemy niskiego poziomu, a po uzyskaniu połączenia możesz dołączyć bardziej rozsądne kody błędów. Możesz to osiągnąć pod względem zakresu lub wagi projektu. Przykład: poziom informacji i ostrzeżenia są częścią specyficznego protokołu twojego projektu i nie powodują przerwania połączenia. Z poważnymi lub krytycznymi wiadomościami zgłaszaj również przy użyciu protokołu projektu, aby przekazać tyle szczegółów, ile chcesz, a następnie zamykając połączenie przy użyciu ograniczonych możliwości przepływu zamkniętego WebSocket.

Należy pamiętać, że kody zamykające WebSocket są bardzo ściśle zdefiniowane, a fraza / komunikat powodu zamknięcia nie może przekraczać 123 znaków (jest to celowe ograniczenie WebSocket).

Ale nie wszystko jest stracone, jeśli potrzebujesz tych informacji tylko z powodów debugowania, szczegóły zamknięcia i jego podstawowa przyczyna są często zgłaszane z dużą ilością szczegółów w konsoli JavaScript Chrome.


4
Joakim, dzięki, bardzo szczegółowa odpowiedź. Jeśli używam sok.onerror=function (evt) {console.log(evt);}szczegółów, to nie jest tak dużo. Ani nawet reasonczy coś. Więc nie ma żadnych opcji? Po prostu pokazuję użytkownikowi, że something is wrong, or not connencted?nie jest zbyt przyjazny dla użytkownika, byłoby miło, gdyby użytkownik widział „Nie można usunąć, przyczyna ograniczeń bazy danych”. Jakieś opcje? Dzięki
slevin

Powinieneś sok.onclosezamiast tego użyć tego, który wyzwala close event, ma reasoniw codenim
Ihab Khattab

@IhabKhattab, który byłby specyficzny dla kodu zamknięcia, a także kiedy nastąpi zamknięcie. posiadanie sok.onclosebędzie działać na wielu ścieżkach, ale nie na wszystkich. Szczególnie zły protokół, złe błędy uzgadniania (jak niektóre warunki, które mogą powodować zamknięcie kodu 1006). Czy to się zmieni w przyszłości? Prawdopodobnie. Ale kiedy napisano tę odpowiedź, była to prawda.
Joakim Erdfelt

@JoakimErdfelt przepraszam, odpowiadałem na @slevin pytanie o nie reasonwróciło, kiedy użył Wskazałem, onerrorże te właściwości codei reasonspecyficzne dla closewydarzenia, a nie errorzdarzenia. więc lepiej byłoby dla niego użyć onclosezamiast tego, czy coś mi brakuje?
Ihab Khattab

@IhabKhattab tak, ponieważ jego pytanie dotyczyło kodu błędu, 1006który ma specjalne znaczenie, i specjalnej obsługi w specyfikacji Websocket oraz JavaScript websocket api. Powód / komunikat w pewnych 1006warunkach nie jest specjalnie i celowo ujawniany nigdzie w API. (jak wskazała odpowiedź). To nie jest błąd w API, a jedynie zajęcie się różnymi specyfikacjami i ich obawami dotyczącymi nadużywania WebSocket do celów innych niż WebSocket.
Joakim Erdfelt

16

W moim i prawdopodobnie @BIOHAZARD przypadku tak było nginx proxy timeout. Domyślnie jest to 60sekunda bez aktywności w gnieździe

Zmieniłem to na 24h nginxi rozwiązałem problem

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

Dzięki za to! To jest przyczyna błędu 1006 w moim przypadku.
Steve Hanov

11

Wygląda na to, że tak jest w przypadku, gdy Chrome nie jest zgodny ze standardem WebSocket. Gdy serwer inicjuje zamknięcie i wysyła ramkę do klienta, Chrome traktuje to jako błąd i zgłasza to stronie JS z kodem 1006 i bez komunikatu o przyczynie. W moich testach Chrome nigdy nie reaguje na zamknięte ramki inicjowane przez serwer (kod zamykający 1000), co sugeruje, że kod 1006 prawdopodobnie oznacza, że ​​Chrome zgłasza własny błąd wewnętrzny.

PS Firefox v57.00 prawidłowo obsługuje ten przypadek i pomyślnie dostarcza komunikat powodujący serwer po stronie JS.


3

Pomyślałem, że to może być przydatne dla innych. Znajomość wyrażeń regularnych jest przydatna, dzieciaki. Zostań w szkole.

Edycja: zamieniono go w poręczną funkcję dandysa!

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)';
}

Stosowanie:

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'
}

Źródło (z drobnymi zmianami dla zwięzłości): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes


1

Wystąpił błąd podczas używania Chrome jako klienta i golang gorilla websocket jako serwera pod proxy Nginx

Wysyłanie co x sekund tylko wiadomości „ping” z serwera do klienta rozwiązało problem


0

To może być Twój adres URL Websocket, którego używasz w urządzeniu, nie jest taki sam (trafiasz na inny adres URL Websocket z Android / iphonedevice)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.