Связь с разъемом фиксированной длины от python до C - PullRequest
0 голосов
/ 27 марта 2020

Работает над обновлением моего приложения, которое использует сокеты для связи из python в программу C, чтобы использовать заголовки фиксированной длины в качестве протокола при отправке сообщений.

В качестве тестового примера моего C Код клиента:

/*
Socket definition code put inside here
*/


char test2[] = "hello this is a test";

uint32_t test = sizeof(test2); //Get size of message and store in 32bit int
uint32_t test_conv = htonl(test); //Convert to network byte order

header = send(ConnectSocket, &test_conv, sizeof(uint32_t), 0); //Send size of message

body = send(ConnectSocket, test2, sizeof(test2), 0); //Send the actual message

Вот выдержка из python Код сервера:

msg = clientsocket.recv(4)

msg_length = int.from_bytes(msg, sys.byteorder) //Get the header with the message length 
msg_length = socket.ntohl(msg_length)
if len(msg) > 0:
    print(f"This message length: {test} ")

msg = clientsocket.recv(msg_length) //Get the message

if len(msg)>0:
    print(f'Message is: {msg.decode("utf-8")}')

Вывод Server.py:

The message length: 21
Message is: hello this is a test

Я опускаю заголовки сокетов и прочее, а также проверка ошибок для экономии места в этом посте.

Это безопасный способ go использовать заголовки фиксированной длины? Я не ожидаю большого количества трафика c, и я буду посылать только предложение или две информации в каждом сообщении.

Мой последний вопрос: почему при вызове send in C я использую '& test_conv' для параметра сообщения. Разве это не просто отправка значения адреса для переменной test_conv. Разве мне не нужно отправлять реальное сообщение, а не адрес?

Спасибо за любую информацию и, пожалуйста, предоставьте любые ссылки на ресурсы, если я должен использовать другую реализацию.

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Мне кажется правильным ваше решение, использующее целое число фиксированного размера, объявляющее количество байтов в следующем сообщении.
Просто обязательно последовательно используйте sizeof и / или strlen() для текстового сообщения в вашем фактическом сообщении. program.
В вашем примере передача sizeof(text2) байтов включает в себя неявное '\0' в конце text2; тогда строка python, которая создается при приеме, содержит этот бесполезный (невидимый, но тем не менее присутствующий) нулевой байт в качестве последнего символа.

Относительно &test_conv в send(), вам нужно понять, что этот системный вызов учитывает только последовательность байтов.
Он не знает, что эти байты состоят из целого числа.
Вот почему вы указываете адрес первого отправляемого байта (&test_conv) и количество байтов, подлежащих отправке. отправлено (sizeof(uint32_t)), начиная с этого адреса.
Получатель получит эту точно такую ​​же последовательность байтов и интерпретирует их как представление в памяти 32-разрядного целого числа (с учетом, конечно, порядка байтов).

Обратите внимание, что пакет struct в python может помочь справиться с представлением в памяти целых чисел и порядком байтов.

0 голосов
/ 27 марта 2020

Мне кажется, вы должны использовать порядок сетевых байтов, а не порядок байтов хоста.

Кроме того, я полагаю, что send () и recv () могут возвращаться рано, без передачи всего, что было запрошено - поэтому они возвращают длины. Обычно они передают все ваши данные и возвращают полную длину, но они не гарантируют этого.

Для python мне нравится мой модуль http://stromberg.dnsalias.org/~dstromberg/bufsock.html. Он позаботится о возобновлении для вас.

Для C, я думаю, что люди просто используют некоторое время l oop для каждого send () и recv ().

...