c socket prog-select()问题

c socket prog-select()问题,c,sockets,select-function,C,Sockets,Select Function,我是网络编程新手。我必须用C编写一个简单的客户机/服务器程序。服务器将侦听连接,客户机将连接到服务器,发送消息,并从客户机接收回显。我们必须使用select来更新它,以同时处理从服务器进程到多个客户端的连接。我试图按照指示在客户端实现select,但我认为在ifFD_ISSETclientSockfd和readfds部分的客户端上有一个无限循环 这是服务器 //server.c #include <stdio.h> #include <unistd.h> #includ

我是网络编程新手。我必须用C编写一个简单的客户机/服务器程序。服务器将侦听连接,客户机将连接到服务器,发送消息,并从客户机接收回显。我们必须使用select来更新它,以同时处理从服务器进程到多个客户端的连接。我试图按照指示在客户端实现select,但我认为在ifFD_ISSETclientSockfd和readfds部分的客户端上有一个无限循环

这是服务器

//server.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <errno.h>


const int ASSIGNED_PORT = 17000;
const int BUF_SIZE = 512;

int main() {

    int serverfd, clientfd;
    struct sockaddr_in serverSock;      //NOTE: a pointer to sockaddr_in can be cast to a pointer to 
    //      a struct sockaddr - useful for connect()

    char buf[BUF_SIZE];
    int errorCheck, msgLength;

    //create socket with error checking (-1 ret on error)
    serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if(serverfd < 0 )
    {
        perror("socket failed.");
        exit(errno);
    }

    //assign sockaddr_in info for server
    bzero(&serverSock, sizeof(serverSock));     //set to all 0's
    serverSock.sin_family = AF_INET;                
    serverSock.sin_addr.s_addr = htonl(INADDR_ANY);
    serverSock.sin_port = htons(ASSIGNED_PORT);


    //bind a name to the socket with error checking (0 ret on success)
    errorCheck = bind(serverfd, (struct sockaddr*)&serverSock, sizeof(serverSock));
    if(errorCheck < 0 )
    {
        perror("bind failed.");
        exit(errno);
    }

    //listen for connections with error checking (0 ret on success)
    errorCheck = listen(serverfd, 10);
    if(errorCheck < 0 )
    {
        perror("listen failed.");
        exit(errno);
    }

    printf("Listening for connections.  Enter CNTRL-c to kill server.\n");

    //create infinite loop to accept, read, write, and close connections with error hecking 
    while(1)
    {

        //accept the connection from the client 
        clientfd = accept(serverfd, 0, 0);
        if(clientfd ==  -1)
        {
            perror("error accepting connection.");
            exit(errno);
        }

        //read data from the client
        bzero(buf, BUF_SIZE);
        msgLength = read(clientfd, buf, BUF_SIZE-1);
        if(msgLength == -1)
        {
            perror("error reading from client");
            close(clientfd);
            close(serverfd);
            exit(errno);
        }

        if(buf[0] '\0')
        {
            printf("connection closing");
            exit(0);
        }
        //print what the client sent
        printf("Message from client: %s\n", buf);

        //echo back what the client sent
        errorCheck = write(clientfd, buf, strlen(buf)+1);   

        if(errorCheck == -1 )
        {
            perror("error writing to client");
            exit(errno);
        }

        //close the connection
        errorCheck = close(clientfd);
        if(errorCheck == -1)
        {
            perror("error closing connection");
            exit(errno);
        }       
    }

    errorCheck = close(serverfd);
    if(errorCheck==-1)
    {
        perror("error closing server, exiting program now");
        sleep(6);
        exit(errno);
    }
    return 0;
}

您需要在服务器端使用select来处理多个客户端,而不是在客户端。

我认为客户端代码中的一个问题是,您正在传递魔法数字32进行选择。那是不对的。您应该传递的是所有套接字编号的最大值,再加上一个。例如,类似这样的内容:

int maxfd = fileno(stdin);
if (maxfd < clientSockFD) maxfd = clientSockFD;
// further maximizations for other sockets would go here, if you had any other sockets...
numfd = select(maxfd+1, &readfds, 0, 0, 0);

请正确格式化您的代码。每行之间都有大量的空行。快速查看可以发现一些问题:您的/0应该是\0两个NUL字符吗?此外,我认为如果buf[0]='\0',请注意用于字符比较的单引号。除此之外,bzero已被弃用,herror未定义。select在连接的任何一端都会有所帮助,具体取决于所需的行为。我首先在服务器端实现了select,我的老师告诉我这不是他想要的,select应该在客户端中,如果您希望一个程序同时处理多个套接字FD,则serverSelect在任何地方都不会有用。它最常用于服务器,因为服务器通常希望能够同时处理多个客户端连接,但它在客户端也很有用,就像您的情况一样,您希望同时处理stdin和TCP套接字上的输入。我感谢你的帮助。我相信我终于让它像老师希望的那样工作了。我想得太多了。@newuser12你的老师提出这个奇怪要求的原因是什么?这是常见行业实践的背对背。因此,可能一个好问题是,我应该如何测试客户端,以查看select函数是否正常工作?我想我可能会感到困惑,因为我所看到的一切都是在服务器端实现select,而不是在客户端实现select。所以,我有点困惑。此外,当我在客户端发送文本字符串时,它限制我在关闭之前只发送3个。为什么会这样?哎呀,我在代码片段中犯了一个错误,要选择的第一个参数应该是maxfd+1,而不仅仅是maxfd。我将编辑我的答案以更正。至于为什么关闭客户端的套接字,可能是因为服务器端设置为只从TCP连接读取单个流,然后关闭TCP连接。
int maxfd = fileno(stdin);
if (maxfd < clientSockFD) maxfd = clientSockFD;
// further maximizations for other sockets would go here, if you had any other sockets...
numfd = select(maxfd+1, &readfds, 0, 0, 0);