在客户端上使用select(..) [英] Using select(..) on client

查看:505
本文介绍了在客户端上使用select(..)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过在客户端上实现select(..)的方式来实现,除了创建TCP套接字以外,还要从服务器创建多个套接字来实现recv(..).我想在使用select(..)创建的不同套接字的不同recv(..)上接收数据.该代码似乎无法按预期运行.请帮忙.谢谢!

I'm trying to implement select(..) on the client side with creating multiple sockets apart from the TCP socket to recv(..) from the server. I want to receive the data on different recv(..) of different sockets created using select(..). The code doesn't seem to function as expected. Please help. Thanks!

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<netinet/in.h>
#include <arpa/inet.h>

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<4;i++)
    {
        if((newsocket[i] = socket(AF_INET, SOCK_STREAM, 0)) > 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; i++){
            if(FD_ISSET(i, &read_fds)) {
                if(i == createsocket) {
                    printf("something is happening..\n");

                    if(newsocket[i] == -1){
                        printf("socket %d\n",i);
                    } else {
                        FD_SET(newsocket[i], &master);
                        if(newsocket[i] > fdmax) {
                            fdmax = newsocket[i];
                        }
                        printf("still something is going on..\n");
                    }
                } else {
                    printf("Doing something..\n");
                    for(j = 0; j <= fdmax; j++) {
                        if(FD_ISSET(j, &master)) {
                            if(j!= createsocket && j!= i) {
                                if((count = recv(createsocket, buffer, bufsize, 0)) > 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,但只会设置具有事件集的那些fd_set.因此,一种方法是从一个干净的状态开始,然后设置我们感兴趣的所有fds.类似这样的东西:

First, we would need to set the file descriptor (fd) -- as many fds, as the application logic demands -- before calling select() everytime in the while loop. We should also set the fd_set to zeros before doing the above step. This is because when select returns, it will return the same fd_set but it will set only those that have the event set. So, one way to do this is to start with a clean state and then set all the fds that we are interested in. Something like this:

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){

第二,创建所有其他套接字(创建套接字套接字除外),打开TCP套接字,但不执行任何操作.如果它是一个客户端,至少,我们将不得不调用connect().如果没有建立显式连接,我们就无法对TCP套接字做任何有用的事情.

Second, you are creating all the other sockets (besides createsocket socket), you open a TCP socket and yet do nothing with it. If it is a client, at the very least, we would have to call connect(). Without setting up an explicit connection, we cannot do anything useful with TCP sockets.

因此,高级别评论是,如果您要拥有N个客户端套接字,请打开N个套接字并将所有套接字连接到服务器.接下来,将所有N个fds传递给select()(每次调用select()),然后循环执行.

So, high-level comment is that if you want to have N client sockets, then open N sockets and connect all sockets to the server. Next, pass all the N fds to the select() (everytime you call select()) and do this in a loop.

这篇关于在客户端上使用select(..)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆