2012-03-17 4 views
1

내 클라이언트 프로그램이 먼저 서버에 연결 한 다음 서버가 파일을 보낸 다음 클라이언트가 명령을 입력하여 서버로 보내고 result를 수신합니다 .i 입력 명령에 io를 사용하여 비보호로 구현하려는 경우 및 비 블로킹 소켓. 하지만 내 프로그램은 stdin.when에서 입력을 읽을 수 없다. 단지 stdin을 read_set으로 설정했는데 작동하지만이 경우에는 작동하지 않는다. 이 내 클라이언트 코드입니다.비 블로킹 소켓 및 io

main (int argc, char *argv[]) 
{ 
    int len, rc,max_sd; 
    int sockfd; 
    int on=1; 
    char recv_buff[100]=""; 
    char command[100]=""; 
    char result[100]=""; 
    char instr_buff[100]=""; 
    struct sockaddr_in addr; 
    struct timeval timeout; 
    fd_set read_set,write_set; 

    /*************************************************/ 
    /* Create an AF_INET stream socket    */ 
    /*************************************************/ 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
    { 
     perror("socket() failed"); 
     exit(-1); 
    } 
    rc = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on)); // Allow socket descriptor to be reuseable 
    if(rc<0) 
    { 
     perror("setsockopt() failed"); 
     close(sockfd); 
     exit(-1); 
    } 
    //Set socket to be non-blocking. 
    rc = ioctl(sockfd, FIONBIO, (char *)&on); 
    if(rc<0) 
    { 
     perror("ioctl() faild"); 
     close(sockfd); 
     exit(-1); 
    } 
    //making stdin to be non-blocking 
    rc = ioctl(0, FIONBIO, (char *)&on); 
    if(rc<0) 
    { 
     perror("ioctl() faild"); 
     close(sockfd); 
     exit(-1); 
    } 
    /*************************************************/ 
    /* Initialize the socket address structure  */ 
    /*************************************************/ 
    memset(&addr, 0, sizeof(addr)); 
    addr.sin_family  = AF_INET; 
    addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    addr.sin_port  = htons(SERVER_PORT); 

    /*************************************************/ 
    /* Connect to the server       */ 
    /*************************************************/ 
    int count=0; 

    do 
    { 
     rc = connect(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)); 
     count++; 
    }while(rc<0&&count<20); 
    if(rc<0) 
    { 
    printf("can not connect to server\n"); 
    exit(-1); 
    } 
    else 
     printf("Connect completed.\n"); 

    timeout.tv_sec = 60; 
    timeout.tv_usec = 0; 
    FD_ZERO(&read_set); 
    FD_ZERO(&write_set); 
    FD_SET(sockfd,&read_set); 
    FD_SET(0,&read_set); 
    while(1) 
    { 
    rc=select(sockfd+1,&read_set,&write_set,NULL,&timeout); 
    if(rc<0) 
    { 
     perror("select failed()\n"); 
     break; 
    } 
    if(rc==0) 
    { 
     printf("select timed out.End Program\n"); 
     break; 

    } 
    if(FD_ISSET(sockfd,&write_set)) 
    { 
     //sending data 
     rc=send(sockfd,command,strlen(command)+1,0); 
     if(rc<0) 
     { 
      perror("sending command failed"); 
      break; 
     } 
     if(rc==0) 
     { 
      printf("connection closed by server\n"); 
      break; 
     } 
     printf("command send\n"); 
     FD_CLR(sockfd,&write_set); 

    } 
    if(FD_ISSET(sockfd,&read_set)) 
    { 
     //receiving data 
     rc=recv(sockfd,recv_buff,sizeof(recv_buff),0); 
     if (rc < 0) 
     { 
      if(errno == EAGAIN||errno == EWOULDBLOCK) 
      { 
       printf("no message\n"); 
       continue; 
      } 
      perror(" recv() failed"); 
      break; 
     } 
     if(rc==0) 
     { 
     printf("connection closed by server\n"); 
     break; 
     } 
     //data received 
     printf("data received\n"); 
     //check to see if is instr.conf or result 
     if(recv_buff[strlen(recv_buff)-1]=='@') //is file 
     { 
     //save to instr_buff 
     strcpy(instr_buff,recv_buff); 
     } 
     else 
     { 
     //result received 
     printf("Result:\n"); 
     printf("%s",recv_buff); 
     } 
     printf("Enter Command:\n"); 
    } 
    if(FD_ISSET(0,&read_set)) 
    { 
     scanf("%s",command); 
     FD_SET(sockfd,&write_set); 
    } 

    }//end of while 

    close(sockfd); 
} 
+1

이 어떻게 실패하는 ? –

답변

1

select업데이트 읽기, 쓰기 것을 기억하고, 예외 당신이 통과 fd_set 항목이 당신이 두 가지 입력에 선택하고있는 경우 그 중 하나는 준비가되어 있음을 의미한다,

/* read_set has two bits set here ... */ 
rc1 = select(maxfd, &read_set, ...); 
/* but now read_set has only one bit set here */ 
rc2 = select(maxfd, &read_set, ...); 

얼마나 많은 파일 디스크립터 것이다 번째 select 전화 확인 : 설정 읽기가 설정 한 비트 만이있다? 하나의 "read ready"만 있으면 첫 번째 호출은 다른 설명자의 비트를 지 웠습니다.

루프가 결코 read_set을 다시 초기화하지 않습니다. 그러므로 두 개의 select 호출을 직접 호출하지 않아도 루프를 통해 두 번째 및 나중의 트립에서 일부 비트가 지워진 select을 호출 중입니다.

(한 전형적인 관용구를 사용하면 통화에서 수정할 수 입력을 위해 사용하고 복사 "마스터 세트"가지고 select이다 사용하는 경우 :

copy_reads = master_reads; 
copy_writes = master_writes; 
rc = select(maxfd, &copy_reads, &copy_writes, ...); 

을 다음 & copy_reads 및 &에 FD_ISSET를 사용을 필요. 또는 copy_writes, 당신은 FD_ZERO를 사용하고 루프를 통해 각 여행 전체 세트를 재 구축 할 수 있습니다.이 문제를 우회하는 또 다른 방법은 완전히 poll, 또는 epoll 또는 kqueues 또는 유사한을 사용하는 것입니다.)

+0

답변 해 주셔서 감사합니다. – Mushtu