Как элегантно отправлять / получать большую C-структуру с помощью Python?
Я начал писать клиентское приложение Python 3.x. Серверное приложение уже существует и написано на C. Сервер предоставляет заголовочный файл C с определением двух структур, используемых для отправки и приема данных через UDP (я использую модуль socket
Python). Проблема в том, что структуры C довольно большие (около 200 элементов каждый). Если я использую struct
модуль Python для упаковки / распаковки данных, не очень элегантное решение будет упаковывать / распаковывать 200 элементов вручную, например:
struct.pack('H...I', data1, ..., data200)
Кроме того, я хочу иметь доступ к полученным / отправленным элементам в Python с использованием синтаксиса типа C. Например, если я делаю на стороне сервера C
send.data.pos = pos;
было бы неплохо (наиболее естественно), если я могу получить доступ к переменной pos
в клиентской части Python следующим образом:
pos = recv.data.pos
Обратите внимание, что вопрос заключается не в том, как автоматически писать структуру в Python из заголовочного файла, как в этом потоке (у меня нет проблем при написании каждого поля структуры один за другим в Python), а скорее, что было бы лучшим способом организовать данные на Python (например, в классах, используя словари и т. д.), которые позволят мне использовать возможности Python и упростить код и легко получить доступ к данным (я бы предпочел использовать только стандартные модули Python, без внешнего программного обеспечения). Какой был бы самый элегантный способ достичь этого?
- Python socket принимает блоки – запрещает приложение покидать
- CTRL-C ведет себя по-другому в Python
- Для входа в консоль Python требуется потоки?
- netcat отправляет дополнительные «X» UDP-пакеты
- Проблемы с перфорацией отверстий TCP
Попробуйте это – работает с 2,7 и 3,2.
Автор сценария:
import struct, collections class CStruct(object): def __init__(self, typename, format_defn, lead_char="!"): self.names = [] fmts = [lead_char] for line in format_defn.splitlines(): name, fmt = line.split() self.names.append(name) fmts.append(fmt) self.formatstr = ''.join(fmts) self.struct = struct.Struct(self.formatstr) self.named_tuple_class = collections.namedtuple(typename, self.names) def object_from_bytes(self, byte_str): atuple = self.struct.unpack(byte_str) return self.named_tuple_class._make(atuple) if __name__ == "__main__": # do this once pkt_def = """\ u1 B u2 H u4 I""" cs = CStruct("Packet1", pkt_def) # do this once per incoming packet o = cs.object_from_bytes(b"\xF1\x00\xF2\x00\x00\x00\xF4") print(o) print(o.u4)
Вывод:
Packet1(u1=241, u2=242, u4=244) 244
Вы можете написать класс, который имеет функции-члены, чтобы упаковать / распаковать данные в атрибуты класса / из класса, используя struct.pack
и т. Д.
Я бы предложил посмотреть на Construct . Но я не думаю, что он портирован на Python 3.x. Construct был на паузе в течение некоторого времени, но недавно был подхвачен новым разработчиком, поэтому, возможно, он вскоре сможет поддерживать Python 3.x.
Возможно, вы сможете использовать dpkt как простой способ доступа к пакетным данным. Взгляните сюда на примеры использования. Для простого примера:
class Foo(dpkt.Packet): __hdr__ = (('type', 'B', 0), ('size', 'B', 0)) data = get_udp_message() foo = Foo(data) if foo.size != len(data): print "Bad size in header" if foo.type == 3: parse_payload(foo.data)
- Временные ряды, строящие несоответствия в Пандах
- исключение catch для python и продолжить попытку блокировки
- Отправить текст «http» через сокет python
- API-интерфейс API-интерфейса App Engine медленнее, чем собственный питон
- неблокирующий сокет, ошибка всегда
- Восстановление из zmq.error.ZMQError: адрес уже используется
- Catch "socket.error: Соединение отказало" исключение
- TypeError: необходим байтовый объект, а не 'str'
- OSError: Конечная точка транспортного средства не подключена
- Как узнать, мертв ли соединение в python
- В этом примере клиентского сервера Python 3 клиент не может отправлять более одного сообщения