2012-04-25 6 views
3

C++로 소켓을 만들었는데 특정 연결 시간 초과가 필요했습니다. 그래서 무슨 일이 일어나고 있는지의 :소켓 읽기 : EAGAIN : 리소스를 일시적으로 사용할 수 없습니다.

  • 그것이 NON_BLOCKING 확인 소켓을 작성
  • 전화 연결
  • 그것은 -1을 반환하고
  • 이 전화
  • 반품> 0을 선택 예상대로의 errno EINPROGRESS, 그래서 연결되었습니다
  • 소켓을 다시 블로킹하십시오.
작품을 좋아

bool mastControl::prepareSocket(char * address, int port, int * sockfd) { 

    struct sockaddr_in serv_addr; 
    struct timeval timeout = {0,100000}; 
    struct timeval connTimeout; 
    struct hostent * server = NULL; 
    fd_set socketSet; 
    socklen_t lon; 
    int sockOpt = 0; 
    long socketFlags = 0; 
    int buffersize = 8; 
    int res = 0; 
    int connectReturn = 0; 
    const int WAIT_TO_RECONN = 15; 

    server = gethostbyname(address); 
    *sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    if (*sockfd < 0) { 
     qDebug()<<"Impossible to open socket: "<<strerror(errno); 
     return false; 
    } 

    if (server == NULL) { 
     qDebug()<<"No such host: "<<strerror(h_errno); 
     return false; 
    } 

    // Initializating server direction struct: 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    bcopy((char *)server->h_addr, 
      (char *)&serv_addr.sin_addr.s_addr, 
      server->h_length); 
    serv_addr.sin_port = htons(port); 

    // Making socked non-blocking in order to set a timeout value for connection: 
    if((socketFlags = fcntl(*sockfd, F_GETFL, NULL)) < 0){ 
     qDebug()<<"Impossible to retrieve sockets descriptor flags "<<strerror(errno); 
     return false; 
    } 
    socketFlags |= O_NONBLOCK; 
    if(fcntl(*sockfd, F_SETFL, socketFlags) <0){ 
     qDebug()<<"Impossible to update sockets descriptor flags: "<<strerror(errno); 
     return false; 
    } 

    connectReturn = connect(*sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)); 
    if(connectReturn < 0){ 
     if(errno == EINPROGRESS){ 
      do{ 
       // Establishing a 15 seconds timeout: 
       connTimeout.tv_sec = 15; 
       connTimeout.tv_usec = 0; 
       FD_ZERO(&socketSet); // Initialising set of sockets as an empty set 
       FD_SET(*sockfd, &socketSet); // Adding socket to set 
       connectReturn = select(*sockfd+1, NULL, &socketSet, NULL, &connTimeout); 
       if(connectReturn<0 && errno!=EINTR){ // Error in select 
        qDebug()<<"Connection error in select function: "<<strerror(errno); 
        return false; 
       } 
       else if(connectReturn>0){ // Socket selected for writing 
        lon = sizeof(int); 
        if(getsockopt(*sockfd, SOL_SOCKET, SO_ERROR, (void*)(&sockOpt), &lon) <0){ 
         qDebug()<<"Unnable to get socket options: "<<strerror(errno); 
         return false; 
        } 
        // Checking the value returned: 
        if(sockOpt){ 
         qDebug()<<"Error in delayed connection: "<<strerror(errno); 
         return false; 
        } 
        break; 
       } 
       else{ // Timeout 
        qDebug()<<"Connection timeout exceeded: "<<strerror(errno); 
        return false; 
       } 
      } while (1); 
     } 
     else{ 
      qDebug()<<"Connection error: "<<strerror(errno); 
      sleep(WAIT_TO_RECONN); // Wait 15 seconds 
      return false; 
     } 
    } 

    //Connected 

    // Must set the socket as blocking again: 
    if((socketFlags = fcntl(*sockfd, F_GETFL, NULL)) < 0){ 
     qDebug()<<"Impossible to retrieve sockets descriptor flags "<<strerror(errno); 
     return false; 
    } 
    socketFlags &= (~O_NONBLOCK); 
    if(fcntl(*sockfd, F_SETFL, socketFlags) <0){ 
     qDebug()<<"Impossible to update sockets descriptor flags "<<strerror(errno); 
     return false; 
    } 

    if (setsockopt (*sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, 
        sizeof(timeout)) < 0) { 
     qDebug()<< "ERR - setsockopt failed"; 
     return false; 
    } 

    if (setsockopt (*sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, 
        sizeof(timeout)) < 0) { 
     qDebug()<< "ERR - setsockopt failed"; 
     return false; 
    } 
    if ((res = setsockopt (*sockfd, SOL_SOCKET, SO_SNDBUF, &buffersize, 
          sizeof(buffersize))) == -1) { 
     qDebug()<< "ERR - setsockopt failed (SO_SNDBUF) = " << res; 
     return false; 
    } 
    //Socket Ready 

    return true; 
} 

:이 부분에 대한

코드는 다음과 같습니다.

bool mastControl::findPacket(int sockfd, st_messageMastToPc * messageReceived, bool * connected) { 

    int n = 0; 
    bool messageFound = false; 
    char * buffer = (char *) messageReceived; 
    unsigned int pos = 0; 

    while (((n = read(sockfd, &(buffer[pos]), 1)) > 0) and not messageFound) { 

     //qDebug() << "read output " << n; 
     if (n == 1) { 
      pos++; 

      if ((pos == 1) && (buffer[0] == 2)) { 
       // Some stuff... 
      } else if ((pos == 2) && (buffer[1] == 2)) { 
       // Some stuff... 
      } else if (pos >= uiMessageMastToPcSize) { 
       messageFound = true; 
       //Complete message received 
      } else if (pos < 2) { 
       // Reseting pos 
       pos = 0; 
      } 
     } 
    } 

    if (n < 0){ 
     qDebug()<< "Disconnected. Reason #" << errno << ": " << strerror(errno); 
     *connected = false; 
    } 

    return messageFound; 
} 

읽기 기능이 errno를로 EAGAIN을주고있다 "자원 일시적으로 사용할 수 없습니다"를 의미 : 나는 새로운 패킷을 읽을 접수가 있는지 확인하는 함수를 호출하고있어 어디 그러나 나는 루프가 있습니다. 그렇다면 내가 연결이 끊어져 있다고 가정하고, 불리언 연결이 이제는 거짓인데, 루프에서 다시 소켓을 생성하려고 다시 시도 할 것입니다.

그래서 처음에는 왜이 오류가 발생하는지 알지 못합니다.

둘째로, 나는 완전히 연결이 끊어 졌는지 알지 못합니다. 아니면이 오류가 발생한 후에 새 소켓을 만들 때 연결을 끊는 사람이 나입니다.

어떤 도움이 필요합니까?

답변

8

EAGAIN은 연결이 끊겼다는 의미가 아니며 "지금 읽을 것이 없습니다. 나중에 다시 시도하십시오"라는 의미입니다.

당신이 중 하나를 해제 O_NONBLOCK fcntl(2)과 (사용 가능한 뭔가가있을 때까지 read 대기 제작), 아니면 그냥 read를 호출하기 전에 select(2) 같은 뭔가 소켓에 기다릴 수 있습니다.

편집 : 코드를 추가 했으므로 소켓에 SO_RCVTIMEO을 설정하고 있습니다. 이로 인해 차단 readEAGAIN을 반환 할 수 있습니다. 그러지 않으려면 SO_RCVTIMEO 만 남겨주세요.

+0

좋아, 그게 내가 기대했던거야. 하지만 내가 말했듯이, 나는 select 후에 소켓을 다시 BLOCKING으로 설정했다. 그 연습이 틀렸어? 매번 전화를 걸기 전에 선택 전화를해야합니까? 뭔가 다른 것을 읽을 때까지 실행을 차단하는 다른 방법은 없습니까? –

+0

어떻게 차단 모드로 설정 했습니까? 당신이'read'를 호출하기 전에 그것이 일어 났을 것이 확실합니까? 'SO_RCVTIMEO' 세트가 있습니까? –

+0

소켓을 작성하고 BLOCKING으로 다시 구성하는 코드를 포함하여 편집했습니다. 그것은 확실히 읽기 전에 발생합니다. 그리고 네, 함수의 끝에서 볼 수 있듯이, 저는 SO_RCVTIMEO를 설정하고 있습니다. (나는 그런 식으로 상속 받았지만 작동하지 않는다고 생각합니다.) 틀렸어? –

관련 문제