在客户端上使用select(..)

我正在尝试在客户端实现select(..),从服务器创建除TCP套接字到recv(..)之外的多个套接字。 我想接收使用select(..)创建的不同套接字的不同recv(..)的数据。 代码似乎没有按预期运行。 请帮忙。 谢谢!

#include #include #include #include #include #include #include #include #include  int main(int argc, char *argv[]) { int count, createsocket, chunks, newsocket[5], i; int bufsize = 2048; char *buffer = malloc(bufsize); char fname[256]; struct sockaddr_in address; fd_set master; fd_set read_fds; int fdmax, j; FD_ZERO(&master); FD_ZERO(&read_fds); if((createsocket = socket(AF_INET, SOCK_STREAM, 0)) > 0) { printf("Socket created.\n"); } address.sin_family = AF_INET; address.sin_port = htons(15001); inet_pton(AF_INET, argv[1], &address.sin_addr); if(connect(createsocket, (struct sockaddr*)&address, sizeof(address)) == 0) { printf("Connected to server %s\n",argv[1]); } printf("Enter the file name to download\n"); scanf("%s",fname); send(createsocket, fname, sizeof(fname), 0); // printf("Enter the chunks of file to receive"); printf("waiting to receive the file from server..\n"); //code to create a new socket based on the number of chunks required for(i=0;i 0) { printf("new Socket %d created.\n", i); } } FD_SET(createsocket, &master); fdmax = createsocket; for(;;) { read_fds = master; if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){ perror("select"); exit(2); } for(i=0; i fdmax) { fdmax = newsocket[i]; } printf("still something is going on..\n"); } } else { printf("Doing something..\n"); for(j = 0; j  0) { perror("recv"); } else { write(1, buffer, count); } } } } } } } } // while((count = recv(createsocket, buffer, bufsize, 0)) > 0) // write(1, buffer, count); printf("EOF.\n"); for(i=0;i<4;i++) { close(newsocket[i]); } return close(createsocket); } 

两个快速评论:

首先,我们需要在while循环中每次调用select()之前设置文件描述符(fd) – 与应用程序逻辑要求一样多的fds。 在执行上述步骤之前,我们还应将fd_set设置为零。 这是因为当select返回时,它将返回相同的fd_set,但它将仅设置具有事件集的那些。 所以,一种方法是从一个干净的状态开始,然后设置我们感兴趣的所有fds。这样的事情:

 FD_ZERO(&read_fd_set); FD_SET(createsocket, &master); // We should do this for all connections if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1){ 

其次,你正在创建所有其他套接字(除了createsocket socket),你打开一个TCP套接字,但却没有做任何事情。 如果是客户端,至少我们必须调用connect()。 如果不设置显式连接,我们就无法对TCP套接字执行任何有用的操作。

所以,高级评论是,如果你想拥有N个客户端套接字,那么打开N个套接字并将所有套接字连接到服务器。 接下来,将所有N fds传递给select()(每次调用select())并在循环中执行此操作。

问题是你在没有准备好阅读的套接字上调用recv() 。 这就是select()用途,告诉你哪些套接字可以读取。 调用recv()逻辑处理整个fds集合,而不仅仅是ready-set中的fds。