Войти
ПрограммированиеФорумВеб

chrome debug websocket

#0
13:59, 27 ноя 2022

Хром упорно не выдает нужной информации по ошибке при попытке открытия веб сокета:

Хром посылает на сервер информацию:

GET / HTTP/1.1
Host: localhost:8001
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://localhost:8000
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=gtked8uan3b7054dv1ec5gts84
Sec-WebSocket-Key: KRPF8gwoyXYsX8uAwUnn7Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Сервер отсылает ответ:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Accept: LRZnjfLzSFkUAxi7/8OxtpKrXAk=

Хром выдает непонятную ошибку:

test_ws.js:17 WebSocket connection to 'ws://localhost:8001/' failed: 
(anonymous) @ test_ws.js:17

Чем можно отладить вебсокеты, для поиска ошибки?

#1
19:56, 27 ноя 2022

Все еще плюхаюсь в вебсокетом под хромом ... даже попробовал фаерфокс - в общем дело не только в хроме

wireshark проверил пакеты по обратной петле - оказалось хром ничего не кеширует, и обрывает соединение как только ему приходит хендшейк.

Оказалось js для тестирования лучше всего вызвать в хроме: dev console, sources, snippets
Прямо в ней запускать и отлаживать и проверять переменные можно после вызова вебсокета ... с вебсокетом я начал разбирваться только после того как нашел ws.readyState - выдавал все время 3, пока я не запустил исходник с гитхаба https://gist.github.com/cn007b/4e9cc1f4fe7d9393c6a0a07747fc78fe стал показывать 0 и 1 - наконец-то сокет создан ...

Вот только возникла новая проблемма - после того как я сервером передаю любые полученные им данные из telnet в браузер - сокет браузера закрывается с ошибкой:

WebSocket connection to 'ws://localhost:8001/' failed: Invalid frame header

И я не знаю в каком направлении дальше копать...

#2
20:17, 27 ноя 2022

Пишешь свою реализацию ws server? Подними для пробы ws сервер на node js, подключись к нему хромом и через wireshark побайтово сравни свои фреймы и фреймы который выдает node версия.

#3
20:18, 27 ноя 2022

Ты же сам в соседней теме написал, что ws больше не поддерживается, только wss.

#4
8:15, 29 ноя 2022

#3

У меня создавалось ощущение, что не поддерживается, потому-что я не мог понять где ошибка.
Но потом меня смутили примеры кода с гитхаба, где вроде бы схема ws работает. Я покопался в инете и нашел, что иногда браузеры разрешают конектиться к локалхосту по ws. Я перестал отправлять в открытый сокет данные и много лазил по настройкам хрома до тех пор пока с консоли снипетов кода хрома не получил ответ - что вебсокет установлен и готов к обмену данными.

#2

Да wireshark очень помог разобраться в проблемме. Сервер вроде заработал. И постепенно приходит понимание того - что для реализации raw ws сервера я слишком туп - наверное надо смотреть в сторону другого языка или php async socket.

Для меня передача JSON обновления данных в браузер через вебсокет оказалась слишком сложной - я научился передовать только короткие сообщения менее 126 байт, типа "JS нам требуется обновление, срочно скачивай с сервера data.json.php"

                $request = "vertex_update";
                $response = chr(129).chr(strlen($request)).$request;
                foreach($this->browsers as $soc)
                {
                        socket_write($soc,$response);
                }

Архитектура приложения оказалась настолько запутаной и сложной для понимания, что сервер валится от простого подключения телнета, и добавление новых фишек выглядит крайне не реальным
В общем, если не хватает мозгов написать собственный вебсокет сервер на пхп, то лучше присмотреться к использованию готовых реализаций php async socket

#5
11:18, 29 ноя 2022

despair1
> Да wireshark очень помог разобраться в проблемме. Сервер вроде заработал. И
> постепенно приходит понимание того - что для реализации raw ws сервера я
> слишком туп - наверное надо смотреть в сторону другого языка или php async
> socket.
Просто прочитать, как оно работает, ещё не пробовал?
https://www.rfc-editor.org/rfc/rfc6455

#6
11:54, 29 ноя 2022

#5

пробовал, но для меня там слишком сложно написано

я вообще, отчаившись думал исходники хрома постотреть чтобы код ошибки выцепить - но это для меня еще сложнее оказалось

Политики безопасности, конечно политиками безопасности, но мне было критически важно получить в js, конкретную причину ошибки послужившую закрытию сокета

#7
13:01, 29 ноя 2022

despair1
> Политики безопасности, конечно политиками безопасности, но мне было критически
> важно получить в js, конкретную причину ошибки послужившую закрытию сокета
Ты неправильно форматируешь его, о чём тебе браузер и сказал. "Invalid frame header" - "неправильный заголовок фрейма".

Посмотри внимательно раздел 5: https://www.rfc-editor.org/rfc/rfc6455#section-5, там даже картинки со схемами есть, как правильно укладывать всё в байты. В том числе, там описывается, что именно значит число 129, и как передавать сообщения длиннее 126 байт.

#8
13:23, 29 ноя 2022
// https://www.rfc-editor.org/rfc/rfc6455#section-5.2
enum FrameType {
    Continuation = 0,
    Text = 1,
    Binary = 2,
    Close = 8,
    Ping = 9,
    Pong = 10,
}

struct Frame {
    is_final: bool;
    frame_type: FrameType;
    payload: ByteString;
}

fn serialize_frame(f: Frame) -> ByteString {
    u8 first_byte = f.frame_type as u8;
    if (f.is_final) {
        first_byte += 128;
    }
    ByteString len_bytes;
    usize length = f.payload.length();
    if (length <= 125) {
        len_bytes =
            ByteString::byte(length as u8);
    } else if (f.payload.length() <= 65535) {
        len_bytes =
            ByteString::byte(126) +
            ByteString::byte((length >> 8) as u8) +
            ByteString::byte((length & 255) as u8);
    } else {
        len_bytes =
            ByteString::byte(127) +
            ByteString::byte((length >> 56) as u8) +
            ByteString::byte(((length >> 48) & 255) as u8) +
            ByteString::byte(((length >> 40) & 255) as u8) +
            ByteString::byte(((length >> 32) & 255) as u8) +
            ByteString::byte(((length >> 24) & 255) as u8) +
            ByteString::byte(((length >> 16) & 255) as u8) +
            ByteString::byte(((length >> 8) & 255) as u8) +
            ByteString::byte((length & 255) as u8);
    }
    return
        ByteString::byte(first_byte) +
        len_bytes +
        f.payload;
}

fn text_frame(t: Text) -> Frame {
    return Frame {
        is_final = true,
        frame_type = FrameType::Text,
        payload = t.encodeAsUtf8(),
    };
}

fn binary_frame(bs: ByteString) -> Frame {
    return Frame {
        is_final = true,
        frame_type = FrameType::Binary,
        payload = bs,
    };
}

fn ping_frame() -> Frame {
    return Frame {
        is_final = true,
        frame_type = FrameType::Ping,
        payload = ByteString::empty,
    };
}

fn pong_frame() -> Frame {
    return Frame {
        is_final = true,
        frame_type = FrameType::Pong,
        payload = ByteString::empty,
    };
}

// https://www.rfc-editor.org/rfc/rfc6455#section-7.4
enum StatusCode {
    NormalClosure = 1000,
    GoingAway = 1001,
    ProtocolError = 1002,
    UnacceptableData = 1003,
    InconsistentData = 1007,
    PolicyViolation = 1008,
    MessageTooLarge = 1009,
    ExtensionsMissing = 1010,
    InternalError = 1011,
}

fn close_frame(status: StatusCode, description: Text) -> Frame {
    let statusId = status as u16;
    return Frame {
        is_final = true,
        frame_type = FrameType::Close,
        payload =
            ByteString::byte((statusId >> 8) as u8) +
            ByteString::byte((statusId & 255) as u8) +
            description.encodeAsUtf8(),
    };
}
#9
13:24, 29 ноя 2022

# 7

rfc я прочитал и почти ничего не понял, до меня не сразу дошло что новая ошибка возникает после отправки данных в сокет - до этого я дня 2 тупил с рукопожатием - там тоже гора ошибок была.

Каким чудом я их все исправил, я до сих пор не понял. И щас любой телнет блочит мой вебсокет сервер.

Я так думаю, перед тем как в 3й раз заглядывать в этот rfc, я почитаю про react и swoole, вдруг с моими мозгами нужного результата через них будет добиться проще, чем через написание вебсокета с 0

Если и они окажутся слишком сложные - попробую поменять язык на питон - на нем сокеты раньше проще писались, или ноде или го

ПрограммированиеФорумВеб

Тема в архиве.