2013-09-28 5 views
1

Я пытаюсь реализовать select (..) на стороне клиента с созданием нескольких сокетов, кроме TCP-сокета, на recv (..) с сервера. Я хочу получать данные по различным recv (..) разных сокетов, созданных с помощью select (..). Кажется, что код функционирует должным образом. Пожалуйста помоги. Благодаря!Использование select (..) на клиенте

#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); 
} 
+0

«Кажется не функционирует должным образом» не является приемлемым описанием проблемы. Больше информации пожалуйста. – EJP

+0

@EJP Ну, используя select на клиенте с подключением tcp, я пытаюсь создать несколько новых сокетов для возврата данных с подключенного tcp-сервера. Поскольку recv является протоколом блокировки, я использую select (..) для возврата данных с сервера в разные вновь созданные сокеты на стороне клиента. Являются ли вещи немного ясными? – Rahul

+0

@ EJP Клиент создает k сокетов TCP (каждый для части, которая должна приниматься по частям) и использует функцию «select (...)» для асинхронного ввода-вывода. То есть клиент загружает куски параллельно и использует мультиплексирование ввода-вывода вместо многопоточности. Когда все куски принимаются, он просто объединяет куски в один файл. – Rahul

ответ

0

Два быстрых комментарии:

Во-первых, мы должны задать дескриптор файла (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 розетки), вы открываете сокет TCP и ничего не делаете с ним. Если это клиент, по крайней мере, нам нужно будет вызвать connect(). Не настраивая явное соединение, мы не можем ничего использовать с сокетами TCP.

Итак, комментарий высокого уровня состоит в том, что если вы хотите иметь N клиентских сокетов, откройте N сокетов и соедините все сокеты с сервером. Затем передайте все N fds в select() (каждый раз, когда вы вызываете select()) и делаете это в цикле.

+0

Я согласен с анализом, я реализовал то же самое, прежде чем я прочитал здесь. Программа отлично работает с одним сокетом, который уже подключен к серверу.Мне нужно обойти, чтобы подключить несколько сокетов на клиенте к одному и тому же серверу. – Rahul

0

Проблема в том, что вы вызываете recv() на сокеты, которые не готовы к чтению. Вот что select()для,, чтобы сообщить вам, какие сокеты готовы к чтению. Ваша логика, вызывающая recv(), обрабатывает всю коллекцию fds, а не только fds в готовом наборе.

+0

Я понял ошибку, что делал. Я исправил код. По крайней мере, я не могу возвращать данные, используя select на 3 из 5 read_fds. Большое спасибо за поддержку. – Rahul

Смежные вопросы