2013-04-22 13 views
5

Piszę program, który odbiera komunikaty UDP, a także pobiera dane od użytkowników, jednak mój STDIN jest nadal blokowany przez select. Kiedy I FD_CLR stdin fd przed wybieraniem program działa poprawnie, wskazując, że gniazdo stdin jest zawsze gotowe do odczytu danych z niego. Próbowałem wprowadzić timeval tv, aby go wyłączyć, ale to też nie działa. Czy powinienem zamykać gdzieś gniazdo lub dzwonić do FD_CLR, gdzie nie jestem? Wynik końcowy powinien być STDIN bez blokowania, ale obecnie blokuje. Thank YouWybierz() blokowanie na stdin, nie upłynie limit czasu

int 
wait_for_input(){ 
      fd_set fds; 
      int maxfd, sd, err, n; 
      struct sockaddr_in addr; 
      char stdbuf[BUFLEN]; 
      unsigned char udpbuf[BUFLEN]; 

      //memset(stdbuf,0x0,sizeof(stdbuf)); 
      memset(stdbuf,0x0,sizeof(udpbuf)); 

      sd = socket(AF_INET, SOCK_DGRAM, 0); 

      if(sd<0) { 
      printf("Failed to Open UDP socket"); 
      } 

      addr.sin_family = AF_INET; 
      addr.sin_addr.s_addr = htonl(INADDR_ANY); 
      addr.sin_port = htons(host_list[0]->port); 
      err = bind(sd,(struct sockaddr *) &addr,sizeof(addr)); 

      if(err < 0){ 
          printf("ERROR: Cant bind port"); 

      } 

          struct timeval tv; 
      while(1){ 
          FD_ZERO(&fds); 
          FD_SET(STDIN_FILENO,&fds); 
          FD_SET(sd,&fds); 
          tv.tv_sec = 1; 
          tv.tv_usec = 0; 
          fflush(stdout); 
          select(sd+1,&fds,NULL,NULL,&tv); 

          // If a UDP message arrives 
          if(FD_ISSET(sd,&fds)){ 
              n = recv(sd,udpbuf,sizeof(udpbuf),0); 
              unpack(udpbuf); 
              recompute_my_dv(); 
              fflush(stdout); 

          } 
          //If console data is entered. 
           if(FD_ISSET(STDIN_FILENO, &fds)){ 
              fgets(stdbuf,sizeof(stdbuf),stdin); 
              parse(stdbuf); 
              printf("server> "); 
              fflush(stdout); 
              FD_CLR(STDIN_FILENO,&fds); 


          } 

        } 



return 0; 
} 
+4

Czy próbowałeś sprawdzić, co zwraca 'select'? –

+0

Czy wiesz, że 'STDIN' jest buforowany liniowo? –

+0

@SergeyL - buforowanie linii odbywa się na poziomie biblioteki lub terminala, a nie w warstwie POSIX. Możliwe jest odczytanie stdin w niebuforowany sposób. – Unsigned

Odpowiedz

0

FD_ISSET nie zwraca 1 (lub true) jeśli masz wiadomość na bufor, który jest gniazdko, zwraca true, jeśli dany deskryptor jest częścią zestawu deskryptora pliku. To jeden problem.

Następna jest to, że twoja pętla powinna się rozpocząć (pętla, która jest) powinna rozpoczynać się przed ustawieniem wyboru i powrócić do tego. Powinieneś przechwycić wartość zwróconą przez select. Wynika to z faktu, że select zwraca liczbę bitów w buforze określonym w argumencie 2 wyboru (odczyt, zapis lub błąd). Więc jeśli określiłeś odczyt jako bufor, będziesz chciał przeczytać, ile kiedykolwiek bitów zostało zwróconych przez select.

Myślę, że to są 2 główne problemy. Mam nadzieję że to pomoże.