#node.js #tcp #erlang #erlang-otp #gen-tcp
#node.js #tcp #erlang #erlang-otp #gen-tcp
Вопрос:
Некоторое время я пытался правильно оформить свои сообщения между моим сервером NodeJS и моим сервером erlang gen_tcp. Я успешно использовал {packet,line}, пока мне не пришлось отправлять большие сообщения с данными, и мне нужно было переключиться на кадрирование размера сообщения.
Я установил gen_tcp в {packet, 2}
и я использую библиотеку из: https://github.com/davedoesdev/frame-stream для стороны декодирования tcp NodeJS. Для него ТАКЖЕ установлен параметр размера пакета 2, и я попробовал вариант размера пакета 4.
Я видел, что для любых сообщений длиной менее 127 символов эта настройка работает хорошо, но любые сообщения длиннее этого имеют проблему.
Я провел тест, отправляя все более и более длинные сообщения из gen_tcp, а затем считывая первые четыре байта, полученные на стороне NodeJS:
в сообщении 127: ЗАГОЛОВОК: 0 0 0 127 Длина кадра 127
в сообщении 128: ЗАГОЛОВОК: 0 0 0 239 <—— Это должно быть 128 Длина кадра 239 <—— Это должно быть 128
Теории:
- Некоторое несоответствие кодировки символов, поскольку оно находится на номере 128 (вероятно?)
- Какая-то ошибка либо в gen_tcp, либо в библиотеке (маловероятно?)
- Проклятие магии Вуду, которое заставляет меня работать в день прав человека (скорее всего)
Данные из wireshark показывают следующее:
Байты заголовка правильно кодируются gen_tcp после 128 символов, поскольку шестнадцатеричные значения выполняются следующим образом:
[00][7e][...] (126 length)
[00][7f][...] (127 length)
[00][80][...] (128 length)
[00][81][...] (129 length)
Таким образом, должно быть, ошибка заключается в том, что библиотека на стороне NodeJS вызывает функции Node readUInt16BE(0) или readUInt32BE(0). Но я проверил конечность, и оба они имеют большой конец.
Если байты заголовка равны [A,B], то в двоичном формате эта ошибка возникает после [00000000 01111111]
Другими словами, readUInt16BE(0) считывает [000000000 10000000] как 0xef? что даже не является конечной опцией …?
Спасибо за любую помощь в решении этой проблемы.
С уважением
Дейл
Ответ №1:
Я понял это, проблема была вызвана установкой сокета для приема в кодировке UTF-8, которая поддерживает ascii до 127.
Не делайте этого: сокет.setEncoding(‘utf8’).
Теперь это кажется очевидным, но одну строку кода трудно определить.