2011-08-19 4 views
2

내 TCP 서버에서 내 TCP 클라이언트로 데이터를 보내려고하면 "잘못된 파일 설명자"오류가 계속 발생합니다. 이것은 소켓의 관점에서 무엇을 의미합니까? 나는 지금 잠시 동안이 일을 해왔으며, 제 코드에 무엇이 잘못 될 수 있는지 보지 못합니다. 그것은 기본적으로 내가 이틀 전에 사용했던 코드와 똑같은 코드를 사용했습니다. 누군가가 소켓을 통해 전송하려고 할 때 불량 파일 기술자의 일반적인 원인이 무엇인지 그리고 그 파일을 검사/수정하는 방법을 알려주 길 바랬습니다. 어떤 도움을 주셔서 감사합니다. 내가 도움이 될 수 있도록 아래에 몇 가지 코드를 게시 할 것입니다.BSD 소켓이있는 잘못된 파일 설명자

/*Waits to connect a client. Returns true if successful*/ 
bool TcpServer::launchServer() { 
int status; 

struct addrinfo hints; 
struct addrinfo *servinfo; //will point to the results 

//store the connecting address and size 
struct sockaddr_storage their_addr; 
socklen_t their_addr_size; 


memset(&hints, 0, sizeof hints); //make sure the struct is empty 
hints.ai_family = AF_INET; //ipv4 
hints.ai_socktype = SOCK_STREAM; //tcp 

//get server info, put into servinfo 
if ((status = getaddrinfo("192.168.2.3", port, &hints, &servinfo)) != 0) { 
    printf("\ngetaddrinfo error: %m", errno); 
    return false; 
} 

//make socket 
fd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); 
if (fd < 0) { 
    printf("\nserver socket failure %m", errno); 
    return false; 
} 

//allow reuse of port 
int yes=1; 
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*) &yes,sizeof(int)) == -1) { 
    perror("setsockopt"); 
    return false; 
} 

//bind 
if(bind (fd, servinfo->ai_addr, servinfo->ai_addrlen) < 0) { 
    printf("\nBind error %m", errno); 
    return false; 
} 

//free up space 
freeaddrinfo(servinfo); 

//listen 
if(listen(fd, 5) < 0) { 
    printf("\nListen error %m", errno); 
    return false; 
} 
their_addr_size = sizeof(their_addr); 


//accept 
comm_fd = accept(fd, (struct sockaddr*)&their_addr, &their_addr_size); 
if(comm_fd < 0) { 
    printf("\nAccept error %m", errno); 
    return false; 
} 

return true; 
} //END LAUNCHSERVER 






void TcpServer::communicate() { 


fd_set read_flags,write_flags; // the flag sets to be used 
struct timeval waitd = {10, 0};   // the max wait time for an event 
int sel;  // holds return value for select(); 
int numRead; //holds return value for read() 
int numSent; //holds return value for send() 
char in[255]; //in buffer 
char out[255]; //out buffer 

//clear buffersz 
memset(&in, 0, 255); 
memset(&out, 0, 255); 


while(!done) { 
    FD_ZERO(&read_flags); 
    FD_ZERO(&write_flags); 
    FD_SET(comm_fd, &read_flags); 
    FD_SET(comm_fd, &write_flags); 
    FD_SET(STDIN_FILENO, &read_flags); 
    FD_SET(STDIN_FILENO, &write_flags); 

    //call select 
    sel = select(comm_fd+1, &read_flags, &write_flags, (fd_set*)0, &waitd); 

    //if an error with select 
    if(sel < 0) 
     continue; 

    //if socket ready for reading 
    if(FD_ISSET(comm_fd, &read_flags)) { 

     //clear set 
     FD_CLR(comm_fd, &read_flags); 

     memset(&in, 0, 255); 

     numRead = recv(comm_fd, in, 255, 0); 
     //if an error, exit 
     if(numRead < 0) { 
      printf("\nError reading %m", errno); 
      myAgent->getRobot()->pauseSensorStream(); 
      done = true; 
     } //end if error 
     //if connection closed, exit 
     else if(numRead == 0) { 
      printf("\nClosing socket"); 
      close(comm_fd); 
      done = true; 
     } //end if connection closed 
     //if message, call getsendback 
     else if(in[0] != '\0') { 
      //std::cout<<"\nClient: "<<in; 
      getSendBack(in); 
     } //end if message 
    } //end if ready for read 


    //if stdin is ready for reading 
    if(FD_ISSET(STDIN_FILENO, &read_flags)) 
     fgets(out, 255, stdin); 


    //if socket ready for writing 
    if(FD_ISSET(comm_fd, &write_flags)) { 

     //printf("\nSocket ready for write"); 
     FD_CLR(comm_fd, &write_flags); 

     //check validity by checking for a digit 
     if(isdigit(out[0])) { 

      //create message to send 
      std::stringstream tosend; 
      tosend<<"@ "<<out; 
      //std::cout<<"\ntosend: "<<tosend.str(); 

      //send 
      //********ERROR HAPPENS HERE PRINTS OUT MESSAGE BELOW****** 
      numSent = send(comm_fd, tosend.str().c_str(), tosend.str().length(), 0); 
     } //end if valid message 
     //if error, exit 
     if(numSent < 0) { 
      printf("\nError sending %m", errno); 
      done = true; 
     } //end if error 
     //wait for message to get there, then clear 
     usleep(5000); 
     memset(&out, 0, 255); 
    } //end if 
} //end while 
} //END COMMUNICATE 

클라이언트 코드는 기본적으로 동일합니다.

+0

'send' 전에'fd'를 인쇄 할 수 있습니까? – cnicutar

+0

내가했는데 comm_fd 값은 4입니다. – Sterling

+0

오류 메시지 전에 코드가 "소켓 닫기"를 인쇄합니까? – SKi

답변

0

은 다음보십시오. 명시 적으로 numSent 및 numRead를 초기화하지 않으면 numSent의 음수가 될 수있는 가비지가 발생하여 out [] 배열에 숫자가 없으면 오류가 발생합니다.

2

errno가 EBADF 인 경우 프로그램에서 "잘못된 파일 설명자"를 인쇄합니다. 보내기의 맨 페이지에서 올린 사람 :

EBADF = 잘못된 설명자가 지정되었습니다.

send() 호출 전에 소켓이 닫혔습니다. 프로그램이 "연결 종료"분기 후 "쓰기 준비"분기로 갈 수 있기 때문에 이러한 일이 발생할 수 있습니다.

else if(numRead == 0) { 
    printf("\nClosing socket"); 
    close(comm_fd); 
    break; 
} 

대신에 : 당신은 당신의 자신의 질문에 대답

else if(numRead == 0) { 
     printf("\nClosing socket"); 
     close(comm_fd); 
     done = true; 
    } 
+0

나는 그 코드에서 ctrl f '연결이 닫힌 경우' – Sterling

+0

네,하지만 코드에 "break"가 필요합니다. 내 대답을 업데이트 했으므로 제안 된 변경 사항을 더 쉽게 볼 수 있습니다. – SKi

+0

아무 것도 바뀌지 않았습니다. 왜 그랬을까요? 더 명확히하기 위해 오류는 프로그램 시작시 발생합니다. 매 0.2 초마다 전송되는 메시지가 있으며 첫 번째 메시지를 보낸 후에 오류가 발생합니다. – Sterling

관련 문제