Поведение ntohl и htonl отличается между Python и C
Я пытаюсь подражать поведению некоторых частей C-программы на Python. Они оба читают двоичный файл, где каждая запись имеет длину-> данные. Программа на C извлекает байт длины из файла, и независимо от того, положительный он или отрицательный, ntohl() вернет правильную длину. Тем не менее, в Python, хотя длина записи совпадает со значением, когда оно отрицательное, я получаю OverflowError:
длина: 419495936
всего: 281
длина: -2147418112
OverflowError: невозможно преобразовать отрицательное число в длинную без знака
по сравнению с C:
длина: 419495936
всего: 281
длина: -2147418112
всего: 384
Что я здесь не так делаю? Как я могу получить Python для получения тех же результатов, что и C?
Редактировать с кодом
Вот код C:
while (fread(&rec_len, sizeof(unsigned int), 1, fp1) != 0) {
printf("length: %d\n", rec_len);
rec_len = ntohl(rec_len);
printf("ntohl: %d\n", rec_len);
А вот и Python:
with open(file, "rb") as f:
pSize = struct.unpack('<i', f.read(4))[0]
print "length: " + str(pSize)
packetSize = socket.ntohl(pSize)
print "ntohl: " + str(packetSize)
while packetSize > 0:
packet = f.read(packetSize)
pSize = struct.unpack('<i', f.read(4))[0]
print "length: " + str(pSize)
packetSize = socket.ntohl(pSize)
print "ntohl: " + str(packetSize)
1 ответ
Вам нужно передать положительное число в htonl(). Если вы не можете изменить способ чтения значения, вы можете использовать следующий код:
>>> socket.htonl((-2147418112) & 0xffffffff)
384L
РЕДАКТИРОВАТЬ: посмотрев на ваш код, вы можете изменить struct.unpack для использования '<I'
который дает вам номер без знака, или даже использовать '>I'
или же '!I'
что отрицает необходимость ntohl() впоследствии.