чтение () / recv () успешно, но буфер неизменен и пуст - PullRequest
0 голосов
/ 09 мая 2018

Я пишу клиенту для чтения данных, отправленных обратно с сервера через сокет по TCP с помощью скрипта c на LINUX.

Сервер работает вечно, и я проверяю, могу ли я получить ответ с netcat localhost [PORT_NUMBER]. Сервер находится в состоянии СЛУШАТЬ при проверке с netstat -nap

Функция recv () возвращает ожидаемое количество байтов, но буфер становится пустым, а strlen (buffer) равен 0. Я также пытаюсь перейти на read (), в котором я не ожидал другого результата, и была показана та же проблема.

Это код.

#include <stdio.h>
#include <string.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int socket_desc, msg_rep_size = 1200, msg_size = 100;
    struct sockaddr_in server;
    char message[msg_size], server_reply[msg_rep_size];

    //Create socket
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }

    server.sin_addr.s_addr = inet_addr("0.0.0.0");
    server.sin_family = AF_INET;
    server.sin_port = htons(31114); // PORT_NUMBER

    //Connect to remote server
    if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
    {
        printf("connect error");
        return 1;
    }
    printf("Connected");


    while (1)
    { 
    // send some data
    bzero(message, msg_size);
    strncpy(message, "REQUEST\n", msg_size);

    if (send(socket_desc, message, msg_size, 0) < 0)
    {
        printf("Send failed");
        return 1;
    }
    printf("Data Send\n");

    // Receive a reply from the server
    bzero(server_reply, msg_rep_size);
    int read_result = recv(socket_desc, server_reply, msg_rep_size, 0); 

    if (read_result < 0)
    {
        printf("Receive failed\n");
        return 1;
    }
    else
    {
        printf("Reply received\n");
        printf("read_result: %d\n", read_result);
        printf("strlen(server_reply): %d\n", (int)strlen(server_reply));
        printf("Reply: %s\n", server_reply);
    }
    usleep(8);
}

return 0;
}

Результат печати в bash:

Data send
Reply received
read_result: 1108 
strlen(server_reply): 0
Reply:

Тот же результат отображается, если я изменяю с

int read_result = recv(socket_desc, server_reply, msg_rep_size, 0); 

до

int read_result = read(socket_desc, server_reply, msg_rep_size);

Спасибо за вашу помощь. Я новичок в программировании сокетов и не могу отследить, что происходит.

PS. Ожидаемый размер байтов от ответа - 1108, что является правильным. Я намеревался указать максимальный размер 1200, чтобы подтвердить получение правильного количества байтов.

PS2. Пожалуйста, не стесняйтесь также прокомментировать стиль кодирования низкого уровня c.

1 Ответ

0 голосов
/ 09 мая 2018

Здесь нет доказательств проблемы, только плохой код. Если recv() вернул 1088, он, безусловно, передал 1088 байт в буфер. Очевидно, что полученные данные начинаются с нулевого байта. Для правильной печати используйте

printf("%.*s\n", read_result, server_reply);

Примечание:

  1. «Ожидаемый размер байтов из ответа - 1108, что правильно». Нет, это не так. Там нет «ожидаемого размера». TCP - это потоковый протокол. Если recv() возвращает положительное число, количество переданных байтов может быть любым от 1 и выше до предоставленной длины буфера. Вы должны кодировать цикл , чтобы точно получить N байт.

  2. Прежде чем предположить, что оно положительное, вы также должны проверить read_result на ноль, что указывает на то, что узел отключился. Не пропустите этот шаг.

  3. strlen(server_reply) не имеет значения. Вы не знаете, есть ли вообще завершающий ноль. Не может быть нулей вообще или нескольких, включая, как в этом случае, один в самом начале.

...