Приложение read() добавляет лишние ‘FF’ в конце.

Вопрос или проблема

Я пытаюсь создать клон redis. Я настроил простой TCP-сервер, который слушает запросы от клиента и обрабатывает их.

//начало фрагмента
        if (server_fd == -1) {
                printf("Ошибка создания сокета: %s...\n", strerror(errno));
                return 1;
        }

        int reuse = 1;
        if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
                printf("Не удалось установить SO_REUSEADDR: %s \n", strerror(errno));
                return 1;
        }

        struct sockaddr_in serv_addr = { .sin_family = AF_INET ,
                .sin_port = htons(6379),
                .sin_addr = { htonl(INADDR_ANY) },
        };

        if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != 0) {
                printf("Ошибка привязки: %s \n", strerror(errno));
                return 1;
        }

        int connection_backlog = 5;
        if (listen(server_fd, connection_backlog) != 0) {
                printf("Ошибка прослушивания: %s \n", strerror(errno));
                return 1;
        }

        printf("Ожидание подключения клиента...\n");
        client_addr_len = sizeof(client_addr);
   
        while (1) {
                client_fd =  accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);

                if (client_fd == -1) {
                        printf("Ошибка приема: %s \n", strerror(errno));
                        return 1;
                }

                child_pid = fork();

                switch (child_pid) {
                        case -1:
                                printf("Ошибка форка: %s \n", strerror(errno));
                                return 1;
                        case 0:
                                // дочерний процесс
                                close(server_fd);
                                handle_client(client_fd);
//конец фрагмента
//начало фрагмента
        ssize_t bytes_read;
        char client_request[1024];
        char *command;

        bytes_read = read(client_fd, client_request, sizeof(client_request));
        if (bytes_read == -1) {
                printf("Ошибка чтения: %s \n", strerror(errno));
                return;
        }
        if (bytes_read < 2) {
                handle_send_usage(client_fd);
                return;
        }
        extract_command(client_request, command);

У меня возникла проблема с извлечением команды. Когда я рассматриваю точные байты client_request в строке, содержащей extract_command, я вижу, что к оригинальному запросу добавляются лишние FF.

gef➤  x/gx client_request
0xffffffffee98: 0x0000ffff474e4950

Пожалуйста, уточните, является ли это обычным поведением, или я что-то упустил?

Я использую

echo -n "PING" | nc localhost 6379

чтобы отправить запрос.

Ответ или решение

Ваша проблема с тем, что в массиве client_request появляются лишние байты FF, вероятнее всего, связана с тем, что вы не корректно обрабатываете данные, считываемые из сокета. Рассмотрим, в чем может быть проблема и как это исправить.

Когда вы вызываете функцию read(), она считывает данные из сокета в буфер (client_request), и переменная bytes_read указывает на количество прочитанных байт. В вашем случае вы получаете байты и затем пытаетесь извлечь команду, однако не учитываете, что массив client_request может быть не полностью инициализирован, особенно если не все байты в нем были заполнены.

Возможные причины проблемы:

  1. Неинициализированный буфер: Если ваш client_request массив не инициализирован полностью до вызова read(), может быть, что его оставшаяся часть содержит мусор, включая значения 0xFF.

  2. Кодирование и операции с строками: Убедитесь, что вы правильно обрабатываете строки из буфера. Если вы не ставите нуль-терминатор в конец прочитанных данных, функции, работающие со строками, могут вести себя непредсказуемо.

  3. Проблемы с длиной сообщения: Если bytes_read меньше размера вашего ожидаемого ввода, и вы не проверяете корректно, сколько байтов было прочитано, это может привести к попытке обработки лишних данных.

Возможные решения:

  1. Инициализируйте буфер перед считыванием:

    memset(client_request, 0, sizeof(client_request));
  2. Убедитесь, что вы правильно завершаете строку нуль-терминатором после чтения:

    client_request[bytes_read] = '\0'; // Завершите строку
  3. Проверяйте, что bytes_read больше нуля:

    if (bytes_read <= 0) {
       printf("No data read or read failed.\n");
       return;
    }
  4. Исправьте функцию extract_command:
    Ваша функция extract_command должна принимать корректный размер данных, чтобы избежать чтения за пределами фактических данных. Например:

    void extract_command(char *request, ssize_t length) {
       // Логика извлечения команды с учетом длины
       ...
    }

Пример исправленного кода:

ssize_t bytes_read;
char client_request[1024];
memset(client_request, 0, sizeof(client_request));

bytes_read = read(client_fd, client_request, sizeof(client_request) - 1); // Оставьте место для нуль-терминатора
if (bytes_read == -1) {
    printf("Read failed: %s \n", strerror(errno));
    return;
}
if (bytes_read < 2) {
    handle_send_usage(client_fd);
    return;
}
client_request[bytes_read] = '\0'; // Завершите строку
extract_command(client_request, bytes_read);

Это должно помочь устранить проблему с лишними FF. Проверьте эти изменения и протестируйте ваш код снова. Успехов в разработке!

Оцените материал
Добавить комментарий

Капча загружается...