Структура распаковки запроса на чтение в реализации TFTP

Что касается RFC TFTP (простой протокол передачи файлов), пакет RRQ/WRQ (запросы на чтение\запись) имеет следующий формат:

    2 bytes     string    1 byte     string   1 byte
    ------------------------------------------------
    | Opcode |  Filename  |   0  |    Mode    |   0 |
    ------------------------------------------------

Режим может быть netascii, octet (эквивалентен двоичному) или mail. Дело в том, что в netascii 8 букв, в октете 5, а в mail 4.

Я создаю свой пакет в своем клиенте следующим образом:

paq = struct.pack('!H'+str(len(fileName))+'sB'+str(len(mode))+'sB', 02, fileName, 0, mode, 0)

Затем я отправляю пакет на сервер, чтобы сервер знал, чего ожидать (чтение в случае RRQ или запись в противном случае).

Дело в том, что я не знаю, как распаковать пакет, если я не знаю длины строк на стороне сервера... Только клиент знает длину файла и длину режима, так как он делает пакет.

Должен ли я отправлять длины на сервер перед пакетом RRQ/WRQ, чтобы знать формат, который следует использовать при распаковке? Есть ли другой способ?

Спасибо!


person Burnsed d    schedule 22.05.2018    source источник
comment
Строки заканчиваются 0 байтом. Найдите этот байт, а затем извлеките строку до него.   -  person Barmar    schedule 23.05.2018
comment
Вы не можете использовать unpack() для извлечения полей, кроме Opcode.   -  person Barmar    schedule 23.05.2018
comment
Вы уверены, что режим binari? Я ожидаю, что это будет binary, так как разработчики TFTP говорили по-английски.   -  person Barmar    schedule 23.05.2018
comment
@Barmar На самом деле существует три режима: netascii, октет (эквивалент двоичного) и почта. Проблема все та же.. разная длина. Как бы вы извлекли строку, пока она не найдет 0?   -  person Burnsed d    schedule 23.05.2018
comment
Если пакет находится в p, p[2:p.find('\0')] - это имя файла   -  person Barmar    schedule 23.05.2018


Ответы (1)


Если полученный пакет находится в массиве байтов p, вы можете искать разделители 0 с помощью find().

opcode = p[0:2].decode('ASCII')
nameEnd = p.find(b'\0', start=2)
filename = p[2:nameEnd].decode('ASCII')
modeEnd = p.find(b'\0', start=nameEnd+1)
mode = p[nameEnd+1:modeEnd].decode('ASCII')
person Barmar    schedule 22.05.2018
comment
Большое спасибо! Я очень ценю это! Я знал, как использовать пакет [ : ], но я не знал, что его можно комбинировать с методом .find()! Я очень ценю вашу помощь! - person Burnsed d; 23.05.2018
comment
Почему бы вам не совместить его с find()? Это просто цифры, неважно, как вы их получите. - person Barmar; 23.05.2018