Сокет Python: не может получить массив int

Я пытаюсь установить межпроцессное взаимодействие между Python и c-программой через winsockets. Отправка строки работает, но теперь я пытаюсь отправить массив int из сокета c в сокет python.

Я уже обнаружил, что мне нужно использовать htonl() для преобразования массива int в поток байтов, так как функция отправки winsock2 не может напрямую отправлять массивы int.

Теперь я хочу использовать ntohl() в сокете python, но функция приема возвращает байты, тогда как ntohl() нуждается в целочисленном значении в качестве входных данных.

Вот мой код

C-Side (только соответствующие части):

uint32_t a[1] = {1231};
uint32_t a_converted[1]={0};
a_converted[0] = htonl(a[0]);
iResult = send( ConnectSocket, ( char *)   a_converted, sizeof( a_converted), 0 );

Python Side (только соответствующие части):

data = connection.recv(16)
data_i = socket.ntohl(data)

2 ответа

Решение

То, что вы получили, является строкой байтов, не вызвало ли исключения? Вы можете использовать модуль struct для распаковки - для 16 байт

struct.unpack('!4I', data)

Значение: распаковать 4 беззнаковых 32-битных целых в сетевом порядке

RTM

(Я не могу проверить это - попробуйте самостоятельно)

РЕДАКТИРОВАТЬ: Упс, не прочитал ваш комментарий до конца. Согласно документации по сокетам, recv должен возвращать объект типа bytes. Если он возвращает объект типа str - вы должны преобразовать его в байты - в Python3 это будет data.encode ()

PS На каком Python вы работаете?

Вы сказали, что вам удалось отправить строки через соединение. Я полагаю, вы отправили char* и получил его в Python в виде строки. Что вы сделали, так это отправили поток байтов.

Теперь вы хотите отправить массив целых чисел. В памяти целые числа снова сохраняются как байты. Каждое целое число может занимать 4/8 байтов. Вы можете проверить это заранее, распечатав

printf("Size of integer is %zu", sizeof(int));

Хорошо, отлично, теперь мы знаем, сколько байтов нам нужно отправить. Скажи, что сейчас 4.

Нам также нужно знать порядковый номер целых чисел, но давайте пока предположим, что это большой порядковый номер.

Это означает, что младший значащий байт будет первым, а старший значащий байт - в конце.

Так что теперь вы можете отправлять целочисленный массив точно в один литр, передавая массив в char* и отправка sizeof(array),

На принимающей стороне у вас просто есть поток байтов. Чтобы преобразовать его в массив целых чисел, необходимо получить 4 байта за раз и объединить их в целое число.

Мы можем сделать это следующим образом.

Скажем, есть всего 10 целых чисел. Вы должны передать эту информацию отдельно как-то.

bytes = connection.recv(10*4)

array = []
for i in range(10):
    x = ord(bytes[i*4+0])
    x += ord(bytes[i*4+1]) << 8
    x += ord(bytes[i*4+2]) << 16
    x += ord(bytes[i*4+3]) << 24
    array += [x]
print x

И вы сможете увидеть свой массив целых чисел.

Здесь функция ord преобразует символ в его эквивалентное целое число ASCII.

Примечания стороны:

Теперь, если ваша система имеет размер целого числа 8 вместо 4, вам нужно расширить тело цикла в python. Это будет идти до 56. Также каждый индекс в байтах будет i*8+...

Аналогично, если порядок байтов другой, порядок элементов будет меняться. В основном индексы на bytes будет идти от i*4+3 в i*4+0,

Другие вопросы по тегам