Клиент / Сервер в бесконечном цикле C терпит неудачу - PullRequest
0 голосов
/ 18 апреля 2019

Я реализую клиент / сервер в Linux с использованием C, после запуска клиента и сервера, сервер ожидает запрос от клиента, и это, кажется, работает, однако я хотел бы, чтобы сервер былвозможность постоянно ждать запросов.Тем не менее он продолжает цикл без остановок, вместо ожидания нового запроса от клиента.

server.c:

int main(void)
{
    int sockfd, newsockfd, portno, clilen, connfd = 0;
    struct sockaddr_in serv_addr, cli_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        printf("socket failed\n");
        exit(0);
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
    {
        printf("setsockopt failed\n");
        exit(0);
    }

    memset((char *) &serv_addr, 0, sizeof(serv_addr));
    portno = 8888;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("bind failed\n");
        exit(0);
    }

    listen(sockfd, 5);

    clilen = sizeof(cli_addr);
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
    {
        printf("accept failed\n");
        exit(0);
    }

    printf("[Server] Connected\n");
    char query[BUFFER_SIZE];
    char result[BUFFER_SIZE];

    while (1)
    {
        connfd = read(newsockfd, query, 20);
        if (connfd > 0)
        {
            printf("success\n");
        }
        connfd = write(newsockfd, "I got your message", 18);
        if (connfd >= 0)
        {
            printf("write back worked\n");
        }
        //close(newsockfd);
        //close(sockfd);
        sleep (1);
    }

    printf("%d", connfd);
    printf("[Server] Done\n");
    return 0;
}

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

client.c:

int main(void)
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        printf("socket failed\n");
        exit(0);
    }

    portno = 8888;
    server = gethostbyname("localhost");
    if (server == NULL)
    {
        printf("gethostbyname failed\n");
        exit(0);
    }

    memset((char *)&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    memcpy((void*)&serv_addr.sin_addr.s_addr, (void*)server->h_addr, server->h_length);
    serv_addr.sin_port = htons(portno);

    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("connect failed\n");
        exit(0);
    }

    printf("[Client] Connected\n");

    char query[BUFFER_SIZE];
    char result[BUFFER_SIZE];

    while (1)
    {
        memset(query, 0, BUFFER_SIZE);
        fgets(query, BUFFER_SIZE, stdin);
        if(strncmp(query, "exit", 4) == 0)
        {
            break;
        }

        n = write(sockfd, query, sizeof(query));
        if (n < 0) {
            printf("can't write\n");
        }

        bzero(result, BUFFER_SIZE);
        n = read(sockfd, result, BUFFER_SIZE);
        if (n < 0) {
            printf("can't read back from server\n");
        }

        printf("%s\n", result);
        sleep(1);
    }
    close(sockfd);
    return 0;
}

С этим кодомСервер просто продолжает работать и бесконечно пишет клиенту «Я получил ваше сообщение».Как мне заставить это ждать?Попытка добавления в close (newsockfd), но, как только я это сделаю, он позволяет мне связаться с сервером только один раз, и второй запрос от клиента не выполняется.

1 Ответ

2 голосов
/ 18 апреля 2019

Проблема в клиенте:

n = write(sockfd, query, sizeof(query));

sizeof(query) совпадает с BUFFER_LEN. Когда сервер делает:

connfd = read(newsockfd, query, 20);

будет выполнено BUFFER_LEN / 20 раз для каждого запроса, отправленного клиентом. Это не бесконечный цикл, но если BUFFER_LEN большое, оно будет повторяться много раз.

Клиент не должен отправлять весь буфер query, только строку, прочитанную из stdin. Это должно сделать:

n = write(sockfd, query, strlen(query));

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

Для получения дополнительной информации см. разница между sizeof и strlen в c

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...