Наименьший тип данных Python для болтовни сокета

Какой самый маленький «пакет» можно отправить через модуль сокета? Мне нужно отправить только 16 бит данных, 2 байта, и это то, что я должен отправить быстро, поэтому я хотел бы, чтобы он был как можно меньше. Я провел несколько «экспериментов», чтобы найти наименьший размер, но ничего не получается меньше 28 байт.

Результаты теста:

sys.getsizeof(2) = 28

sys.getsizeof(0b0001) = 28

sys.getsizeof(bytes(0b0001)) = 34

sys.getsizeof('0001') = 66

sys.getsizeof('a') = 60

sys.getsizeof(0b0001000100010001000100010001) = 28

sys.getsizeof(0b000100010001000100010001000100010001) = 32

Мне просто интересно, действительно ли это наименьшее, что я могу отправить.


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

1) Кажется, я не могу сохранить двоичную переменную, она всегда возвращается к целому или другому типу.

2) После тестирования я сделал преобразование двоичного кода в байт и получил это как размер:

sys.getsizeof(bytes(0b0001001001001001001001001)) = 2396778

person user1642826    schedule 06.09.2012    source источник
comment
это системно-зависимые значения в моей системе sizeof('a') = 25 и `sizeof(2) = 12   -  person Joran Beasley    schedule 07.09.2012
comment
Так можно ли заставить сокет принимать только два бита?   -  person user1642826    schedule 07.09.2012


Ответы (3)


sys.getsizeof возвращает внутренний размер целого числа Python, а не целого числа C. Вы можете использовать struct.pack для получения байтов C:

>>> import struct
>>> struct.pack('H',32768)  # default endian-ness
'\x00\x80'
>>> struct.pack('>H',32768)  # force big-endian
'\x80\x00'

Чтобы отправить два явных байта:

>>> struct.pack('BB',100,200)
'd\xc8'

Обратите внимание, что байты представлены в виде строки. 'd' — это символ ASCII для 100, а \xc8 — шестнадцатеричная запись для 200:

>>> ord('d')
100
>>> 0xc8
200

Вы можете получить результирующий размер пакета, созданного с помощью .pack. Например, размер двух шорт и длинного:

>>> struct.calcsize('>HHL')
8

См. документацию модуля struct.

person Mark Tolonen    schedule 07.09.2012
comment
Спасибо, это то, что я искал. - person user1642826; 07.09.2012
comment
Большой! Если ответ приемлем, щелкните зеленую галочку слева. Добро пожаловать в Stack Overflow! - person Mark Tolonen; 07.09.2012

Отвечая на вторую часть вашего вопроса:

«двоичный» — это представление целого числа, а не типа. Вы можете использовать bin() для получения двоичного представления в виде строки. Вы можете преобразовать представление двоичной строки в int, используя.... int(). например

>>> x = 1234
>>> bin(x)
'0b10011010010'     # note, this is a string
>>> print int(bin(x), 2)
1234

Что касается второй части, я думаю, что вы должны ошибаться:

>>> bytes(0b0001001001001001001001001)
'2396745'
>>> sys.getsizeof(bytes(0b0001001001001001001001001))
44
person mhawke    schedule 07.09.2012

Количество байтов, отправляемых через сокет, зависит не только от размера значения данных в языке программирования. Например, отправка одного байта по новому TCP-соединению на «www.google.com:80» приводит к следующему потоку пакетов:

A->B: 64 byte TCP SYN
B->A: 60 byte TCP SYN+ACK
A->B: 52 byte TCP ACK
A->B: 53 byte TCP packet containing a single byte payload
B->A: 52 byte TCP ACK
A->B: 52 byte TCP FIN
B->A: 52 byte TCP FIN+ACK
A->B: 52 byte TCP FIN

Таким образом, для отправки одного байта полезной нагрузки требуется всего 437 байтов. UDP немного более снисходителен, в результате чего для одного байта полезной нагрузки отправляется всего 29 байтов. Вы можете уменьшить полезную нагрузку до 21 байта, если используете необработанный сокет.

В любом случае, уменьшение количества байтов в полезной нагрузке до 1 и использование минимального протокола (например, в большинстве случаев UDP) — это то, что вы получите. Размеры ключей следующие:

IP Header = 20 bytes
IP Header + UDP Header = 20 + 8 = 28 bytes
IP Header + TCP Header = 20 + 20 = 40 bytes

Все различные сетевые протоколы ограничивают количество байтов полезной нагрузки целыми байтами.

Еще одна вещь, которую следует помнить, это то, что под заголовком IP у вас есть любой лежащий в основе физический уровень. В случае стандартного Ethernet все заканчивается тем, что все разбивается на пакеты по 1500 байт. Не имеет значения, отправляете ли вы 1 байт или 1000 байт, в итоге вы отправляете по сети 1500 байт. Конечно, это сильное упрощение, но идея должна была укорениться — если вы работаете в стандартном Ethernet, то я бы не стал сильно беспокоиться об отправке нескольких байтов. Ограничьте использование UDP, если вам не нужны подтверждения.

Если вы действительно заинтересованы, возьмите экземпляр знаменитой серии TCP/IP Illustrated.

person D.Shawley    schedule 08.09.2012