Неправильные значения int, используя fwrite в C - PullRequest
0 голосов
/ 30 ноября 2018

Я пытаюсь создать менеджер ключей для простого клиент-серверного приложения UDP в C. У меня возникают проблемы с записью ключей в текстовый файл.В настоящее время я сохраняю структуры в текстовый файл, но мой вывод был таким же, когда я использовал целые числа.

// ...
// if the principal is requesting to registering, store it in a file
if (req.request_type == regista) {
    printf("Writing key to file...\n");
    pFile = fopen("crypt.txt", "ab");
    fwrite(&req, sizeof(struct P2Key), 1, pFile);
    printf("Written: %u %i ", req.principal_id, req.public_key);
    fclose(pFile);
    printf("Done\n");
}

// if pincipal is requesting key
if (req.request_type == request_key) {
    pFile = fopen("crypt.txt", "rb");
    printf("Key requested for: %u %i ", req.principal_id, req.public_key);
    printf("Searching for Requested Key\n");

    while (fread(&res, sizeof(struct P2Key), 1, pFile) == 1) {
        printf("Read: %u %i\n", res.principal_id, res.public_key);
        printf("Line Number: %ld\n", ftell(pFile));

        // if this is the client requested, send the key
        if (req.principal_id == res.principal_id) {
            send_key.principal_id = req.principal_id;
            send_key.public_key = req.public_key;
            printf("Sending Key...\n");
            // ...
        }

Вот структура, записываемая в файл

typedef struct P2Key {
    enum {
        regista, request_key
    } request_type; /* same size as an unsigned int */
    unsigned int principal_id; /* client or server identifier */
    int public_key; /*  public key */
} P2Key;

ВыводЯ получаю, когда пытаюсь прочитать файл:

 Writing key to file...
 Written: 2 7 Done
 ...
 Writing key to file...
 Written: 1 7 Done
 Key requested for: 2 7 Searching for Requested Key
 Read: 512 1792
 Line Number: 12
 Read: 256 1792
 Line Number: 24
 End of file reached.

Я занимаюсь этим часами, любая помощь приветствуется.

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

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

I baseэто на следующем:

  1. Вы просто добавляете структуру к существующему файлу, независимо от того, сколько байтов в данный момент находится в файле;и
  2. Значения, которые вы читаете, являются точными кратными 256.Что еще более важно, они 256 умножаются на 1, 2 и 7 (256, 512 и 1792).

Простой способ проверкипросто удалите файл (или очистите его) и снова запустите вашу программу.Если у вас больше ничего не записывается в файл, все должно работать нормально.


Существуют способы, с помощью которых вы можете уловить проблему такого рода, если вы так склонны.В их числе, среди прочего:

  • проверка того, что размер файла является точным кратным размеру структуры при открытии.
  • добавление поля (или полей) индикатора в вашу структуру для проверкикаждый элемент, такой как поле в начале, называемое check_dead, и другое в конце, называемое check_beef, которое вы всегда устанавливаете в 0xdead и 0xbeef при записи записи и всегда проверять при чтении одного.
0 голосов
/ 30 ноября 2018

Ваша программа работает здесь.Обратите внимание, что я использую Linux, но, поскольку вы используете b в своих fopen аргументах, даже если вы используете WinX, он все равно должен быть таким же.

Мне пришлось синтезировать некоторые отсутствующиеэлементы, чтобы получить полную программу.Я передал req из main, поэтому функция [new] action должна была использовать req->* вместо req.*, но в остальном она должна совпадать с вашим кодом:


#include <stdio.h>

typedef struct P2Key {
    enum {
        regista, request_key
    } request_type;                     /* same size as an unsigned int */
    unsigned int principal_id;          /* client or server identifier */
    int public_key;                     /* public key */
} P2Key;

void
action(P2Key *req)
{
    FILE *pFile;
    P2Key res;
    P2Key send_key;

    printf("request_type=%d regista=%d request_key=%d\n",
        req->request_type,regista,request_key);

// ...
// if the principal is requesting to registering, store it in a file
    if (req->request_type == regista) {
        printf("Writing key to file...\n");
        pFile = fopen("crypt.txt", "ab");
        fwrite(req, sizeof(struct P2Key), 1, pFile);
        printf("Written: %u %i ", req->principal_id, req->public_key);
        fclose(pFile);
        printf("Done\n");
    }

// if pincipal is requesting key
    if (req->request_type == request_key) {
        pFile = fopen("crypt.txt", "rb");
        printf("Key requested for: %u %i ", req->principal_id, req->public_key);
        printf("Searching for Requested Key\n");

        while (fread(&res, sizeof(struct P2Key), 1, pFile) == 1) {
            printf("Read: %u %i\n", res.principal_id, res.public_key);
            printf("Line Number: %ld\n", ftell(pFile));

            // if this is the client requested, send the key
            if (req->principal_id == res.principal_id) {
                send_key.principal_id = req->principal_id;
                send_key.public_key = req->public_key;
                printf("Sending Key...\n");
                // ...
            }
        }

        fclose(pFile);
    }
}

int
main(void)
{
    P2Key req;

    while (1) {
        printf("Cmd (regista=%d request_key=%d): ",regista,request_key);
        fflush(stdout);
        scanf("%d",&req.request_type);
        scanf("%u %d",&req.principal_id,&req.public_key);

        action(&req);
    }
}

Вот вывод, который я получил:

Cmd (regista=0 request_key=1): 0 5 6
request_type=0 regista=0 request_key=1
Writing key to file...
Written: 5 6 Done
Cmd (regista=0 request_key=1): 0 8 9
request_type=0 regista=0 request_key=1
Writing key to file...
Written: 8 9 Done
Cmd (regista=0 request_key=1): 1 8 9
request_type=1 regista=0 request_key=1
Key requested for: 8 9 Searching for Requested Key
Read: 1 2
Line Number: 12
Read: 5 6
Line Number: 24
Read: 8 9
Line Number: 36
Sending Key...
Cmd (regista=0 request_key=1): ^C
0 голосов
/ 30 ноября 2018

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

Мой первый подозрение: вы добавляете файл в течение долгого времени, и он имеетстарые данные в начале, которые не совпадают с вашей структурой.Я предлагаю сначала очистить файл.В UNIX / Linux вы можете сделать это с помощью «> crypt.txt» из оболочки.

Теперь приступим к отладке кода.Захватите возвращаемое значение всех операций чтения и записи, они возвращают size_t, так что вы можете хотя бы посмотреть возвращаемое значение в отладчике.Возможно, вы захотите записать ошибку и т. Д., Если вы не записали ожидаемое количество байтов - размер структуры.Перейдите к записи и закройте в своем отладчике, затем посмотрите на файл с помощью шестнадцатеричного дампа или аналогичной утилиты.Значения в файле выглядят так, как вы ожидаете?Содержит ли файл то же количество байтов, что и размер вашей структуры?

Затем перейдите к прочитанному коду.Посмотрите, как код загружает каждое значение из файла с помощью fread.Посмотрите возвращаемое значение, которое вы получаете от Fread - это размер вашей структуры?Посмотрите на значения в структуре после завершения чтения.Похоже ли это читать то, что вы написали?

...