Поведение 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() впоследствии.

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