У меня есть некоторый опыт программирования сокетов с использованием API сокетов Berkeley на C. Как правило, любое программирование сокетов требует стратегии, позволяющей получающему сокету знать, сколько данных он должен получить. Это может быть достигнуто либо с помощью полей длины заголовка, либо с помощью символов-разделителей. Как правило, я предпочитаю поле заголовка, которое содержит длину.
Конечно, нам также необходимо знать размер самого поля заголовка длины, которое является просто фиксированным значением размера, которое должно быть согласовано как отправителем, так и получателем. В C это легко реализовать, потому что собственные целочисленные типы имеют фиксированный размер и в двоичном формате, так что вы можете просто сказать что-то вроде:
uint16_t bytes_to_receive;
recv(sock, &bytes_to_receive, sizeof(bytes_to_receive), 0);
bytes_to_receive = ntohs(bytes_to_receive);
// Now receive 'bytes_to_receive' bytes...
Но как такого рода идиомы достигаются с помощью сокетов Python? В Python целые числа являются объектами, а засоленные целые числа - байтовыми массивами переменной длины. Поэтому мы не можем использовать засеченное целое число в качестве поля заголовка длины, потому что мы не можем быть уверены в его размере в байтах.
Конечно, я всегда мог отправить байтовый массив известного размера, содержащий двоичное целое число, например b'\x05\x00'
, чтобы создать 16-разрядное двоичное целое число со значением 5 в формате с прямым порядком байтов, но это действительно не кажется как правильный подход.
Итак, как это обычно выполняется в Python?