C套接字编程中的Recv在发送时冻结?

C套接字编程中的Recv在发送时冻结?,c,sockets,networking,send,recv,C,Sockets,Networking,Send,Recv,所以我一直在遵循Beej的指南,尝试学习一些基本的人际网络- 所以我决定使用一些为练习而编写的代码-所以我尝试制作一个简单的终端聊天室,其中输入的IP地址允许用户连接-我遇到的问题是,在我编辑的这个“服务器”文件中,它在发送信息时工作得很好,但是recv函数调用由于某种原因冻结了终端,我不知道为什么。我假设当accept正确工作时,新的_fd套接字可以用于发送和接收,因为它代表客户端的套接字…这就是我被卡住的地方 此外,我还想知道我应该学习哪些其他图书馆来获得更实际的网络经验。我觉得这是一个很好

所以我一直在遵循Beej的指南,尝试学习一些基本的人际网络-

所以我决定使用一些为练习而编写的代码-所以我尝试制作一个简单的终端聊天室,其中输入的IP地址允许用户连接-我遇到的问题是,在我编辑的这个“服务器”文件中,它在发送信息时工作得很好,但是recv函数调用由于某种原因冻结了终端,我不知道为什么。我假设当accept正确工作时,新的_fd套接字可以用于发送和接收,因为它代表客户端的套接字…这就是我被卡住的地方

此外,我还想知道我应该学习哪些其他图书馆来获得更实际的网络经验。我觉得这是一个很好的方法,可以让我的脚沾满真正低级的东西(我喜欢它,因为它很深),但与其他东西相比,我并不认为C网络库特别有效-

int waiting = 1;
char input = ' ';
char message[100];
memset(&message, 0, sizeof message);

while(waiting) {  // main accept() loop
    sin_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    if (new_fd == -1) {
        perror("accept");
        continue;
    }

    inet_ntop(their_addr.ss_family,
        get_in_addr((struct sockaddr *)&their_addr),
        s, sizeof s);//converts an IP address we get signal from to readable string
    printf("%s wants to chat with you.\nAccept? Y/n\n", s);
    scanf("%c", &input);


    if (input == 'Y' || input == 'y') {

        int rv;

        /*if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("client: connect");
            continue;
        }*/

        waiting = 0;
    }
    else {
        printf("Waiting Mode\n");

    }
}

char buf[100];
char prev[100];
char nil[100];
memset(nil, 0, sizeof nil);
int numbytes;

while (1) {

        fgets(message, 100, stdin);


        if (send(new_fd, message, 100, 0) == -1) {
            perror("send");
        }


        if ((numbytes = recv(new_fd, buf, 100, 0)) == -1) {
            perror("recv");
            exit(1);
        }

        /*if (strcmp(prev, buf) == 0 || strcmp(nil, buf) == 0 ) {
            continue;
        }

        buf[numbytes] = '\0';
        printf("\n%s\n", buf);
        memmove(prev, buf, sizeof buf);*/


}

return 0;

}

如上所述,您的终端“冻结”是由于您在
recv
上的呼叫阻塞造成的。除非聊天室的其他成员发送额外信息,否则您的程序将永远坐在那里等待。你提到的指南是网络编程的很好参考。返回并再次阅读第7.1节和第7.2节中关于阻塞的内容,特别是他在cheezy聊天室示例中对select()的使用。它们使示例能够在不被卡住的情况下工作


如果您不熟悉
select()
pselect()
、和
poll()
,请不要感到沮丧,它们是C语言中最重要但最具挑战性的几个方面,值得交朋友。花点时间回顾一下本指南的第7.1节和第7.2节,花点时间理解select(),这将解决您的问题
select()
pselect()
poll()
对网络的作用不受限制,它们在程序IO的各个方面都很重要。

默认情况下,
recv
将被阻止,直到收到数据。如果用户选择不接受聊天,此代码也不会关闭
new\u fd
。当等待循环退出并开始读取时,您可能已经泄漏了连接。好的-通过选择部分阅读,我有点理解它,但我想确保我在概念上理解它-通过部分阅读,我想我理解它,但只是为了确保文件描述符有某种“准备读取”,“准备写入”和“当前有异常”“选择可以描述的特征。当您使用FD_SET时,对于文件描述符和读、写和异常集,select将告诉您这些文件的哪些特征当前设置为true-因为套接字描述符是更具体的文件描述符,所以它们继承了这些特征?当他使用STDIN作为0时,0是默认的C值还是他任意选择的值?这就是选择的目的和魔力。FD_SET将文件描述符添加到select监视的集合中。如果数据可在给定文件描述符上读取,FD_ISSET将返回true。与“文件描述符”相比,“套接字文件描述符”没有额外的魔力,它是Linux——一切都是一个文件。