C 无限循环中的客户端/服务器失败

标签 c linux client-server

我正在使用 C 在 linux 中实现客户端/服务器,在启动客户端和服务器之后,服务器正在等待来自客户端的查询并且这似乎正在工作,但是,我希望服务器能够能够不断地等待查询。然而它一直不停地循环,而不是等待来自客户端的新查询。

服务器.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;
}

如您所见,我已尝试添加关闭命令,但它们所做的似乎只是完全停止连接,这意味着我无法在第一个之后发送查询。

客户端.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) 但一旦我这样做,它只允许我联系服务器一次,来自客户端的第二个查询失败。

最佳答案

问题出在客户端:

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()),您应该继续阅读直到获得换行符。

有关详细信息,请参阅 difference between sizeof and strlen in c

关于C 无限循环中的客户端/服务器失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55753156/

相关文章:

c - 如何有功能发出单独的牌手来分开人

c - gdb 奇怪的回溯

linux - 如何在 Haproxy 后面添加/删除新服务器且中断最少

java - 每个客户端一个线程是答案吗?

c - 删除从循环调用的函数中的 switch-case

c - 尝试创建多个 if-else 条件

.net - 在 Linux 中使用 Mono.NET 库

linux - 使用 WinSCP 在不同帐户之间切换用户

C、绑定(bind)失败: `Address Already in Use`

java - 在 Java 中发送和接收序列化对象 - Socket 编程