在Beej的网络编程指南之后实现聊天客户端

时间:2015-03-13 15:45:37

标签: c sockets network-programming posix

我正在尝试按照Beej's guide学习网络编程。我已编译the server in section 7.2,使用select(),现在我正在尝试为该服务器编写客户端,因此我可以在我的计算机上打开两个终端并且能够聊天。

我已经开始使用client he gives as an example in section 6.2了,我可以看到,如果我连接到localhost,服务器就会接受连接,所以我从那里开始。

我所做的是在接受与服务器的连接后立即编辑部件(在freeaddrinfo(servinfo); // all done with this structure之后),这是我添加的代码的一部分。

while (1) {

    FD_ZERO(&readfds);
    FD_ZERO(&writefds);

    FD_SET(STDIN, &readfds);
    FD_SET(sockfd, &writefds);

    fcntl(STDIN, F_SETFL, O_NONBLOCK);

    if (select(sockfd+1, &readfds, &writefds, NULL, NULL) < 0) {
        close(sockfd);
        perror("client: select");
        exit(1);
    }

    if (FD_ISSET(sockfd, &writefds)) { // got data from socket, write it to console
        numbytes = recv(sockfd, buf, MAXDATASIZE, 0);
        buf[numbytes] = '\0';
        printf("%s\n", buf);
    }

    if (FD_ISSET(STDIN, &readfds)) { // got data from stdin, write it to socket
        fgets(buf, MAXDATASIZE, STDIN);
        send(sockfd, buf, strlen(buf), 0);
    }
}

尝试运行此代码时,我注意到recv()永远不会返回。我知道这段代码远非完美,但这是我第一次使用套接字,所以我很想得到一些有关我在这里做错的指导。

1 个答案:

答案 0 :(得分:1)

recv(2)是一项阅读操作,因此sockfd应该放在readfds而不是writefds

(顺便说一下,STDIN来自哪里?在POSIX系统上,你可以使用STDIN_FILENO。)

您已经说过这是一个简单的测试代码(可能会在实践中按预期工作),但万一您不了解它:recv()可能会随意拆分数据。作为一个极端的例子,它可以一次返回一个字节。