2011-01-24 4 views
2

카메라에서 비디오를 가져 오기 위해 소켓 클라이언트가 HTTP를 통한 RTSP를 통해 IP 카메라와 통신하도록 함축했습니다.EAGAIN on recv()

카메라와의 통신을 설정하려면 먼저 HTTP-GET 터널을 설정 한 다음 RTSP 명령을 보내야합니다. 카메라가 연결을 잃었을 때 프로그램은 터널 처리기를 닫고 스레드를 끝내야하며 프로세스가 주 기능으로 돌아 가면 통신을 시작합니다 (트레드를 시작하는 등).

다시 연결시 : http-get 터널이 정상적으로 연결되고 "HTTP OK"를 수신하므로 프로그램이 RTSP "DESCRIBE"를 전송하지만 recv는 항상 EAGAIN 오류를 반환합니다. wireshar를 사용하여 DESCRIBE OK 응답이 카메라에서 전송되었지만 recv는이를 가져 오지 않습니다.

struct sockaddr_in aServer; 
    // string myData; 
    char *myData=new char [256]; 
    connection *c=(connection*)vargp; 


    memset(&aServer, 0, sizeof aServer); 
    aServer.sin_family = AF_INET; 

    aServer.sin_addr.s_addr = inet_addr(c->theServer.c_str()); 
    if (aServer.sin_addr.s_addr == INADDR_NONE) 
    { 
    struct hostent *hp; 

    hp = gethostbyname(c->theServer.c_str()); 
    if (hp != NULL) 
    { 
     memcpy(&aServer.sin_addr, hp->h_addr, hp->h_length); 
     aServer.sin_family = hp->h_addrtype; //Protocol family 
    } 
    else 
      cout << "Failed to resolve " << c->theServer.c_str() << ": " << hstrerror(h_errno) << endl; 
    } 

    aServer.sin_port = htons(c->thePort); 
    c->fd_get = socket(AF_INET, SOCK_STREAM, 0); 

    struct timeval timeout; 

    timeout.tv_sec = 5; 
    timeout.tv_usec = 0; 

    setsockopt(c->fd_get, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); 

    if (c->fd_get < 0){ 
    cout << "fd_get < 0" << endl; 
     c->bFin=true; 
     c->WakeUP(); 
     } 
    if (connect(c->fd_get, (struct sockaddr *) &aServer, sizeof aServer) < 0){ 
    cout << "connect fd_get < 0" << endl; 
    c->bFin=true; 
    c->WakeUP(); 
    } 
    if(!c->bFin){ 

    sprintf(myData, "GET %s HTTP/1.1\r\n", c->theURI.c_str()); 
    sprintf(myData, "%sx-sessioncookie: %s\r\nAccept: application/x-rtsp-tunnelled\r\nAuthorization: %s\r\n\r\n", myData,c->theHTTPSessionId.c_str(), c->addAuthorization(c->aGlobalUsername, c->aGlobalPassword).c_str()); 

    cout << myData << endl; 
    write(c->fd_get, myData, strlen(myData)); 

    //LISTENING... 
    int theLen=1500; //3000; 
    int ret=0; 
    unsigned char datosRecibidos[3000]; 

    int flags =fctl(c->fd_get, F_GETFD; 
    if((flags & O_NONBLOCK) == O_NONBLOCK){ 
     fprint(stderr, "yup, its nonblocking"); 
    } 
    else{ 
     fprint(stderr, "nope, its blocking"); 
    } 


    while (c->bFin==false){ 

    ret = read(c->fd_get, ReceivedData, theLen); 
    // ret= recvfrom(c->fd_get, ReceivedData, theLen, 0, (struct sockaddr *) 0, (socklen_t*)0); 
    if (ret == 0) 
    { 
     cout << "Server closed connection: 0" << endl; 

    } 
     else 
     if (ret == -1){ 
    fprintf (stderr, "\n[%d]: %s %d\n", __LINE__, strerror (errno), errno); 

    if(errno==107 ||errno==EAGAIN){ 
     cout << "errno" << endl; 
     c->bFin=true; 
     c->WakeUP(); 
     cout << "vuelta wakeUP" << endl; 
     break;// empezar de nuevo 
    }else{ 
     cout << "errno" << endl; 

    } 

    } 
    else{ 
    //cout << (string)ReceivedData[0]<< endl; 
    c->ProcessReceivedData(ReceivedData, ret); 
    usleep(10); 
    } 
    } 

    close(c->fd_get); 
    c->fd_get = -1; 

    } 

그것이 시간 제한 문제가 될 수 없습니다 : 여기

코드인가? 또는 스택 문제? 어떻게 해결할 수 있습니까?

미리 도움을 주셔서 감사합니다. 친애하는.

cristina

+1

이름'EAGAIN' 당신이 시도해야 제안을 무엇? –

답변

1

소켓이 O_NONBLOCK 모드로 열려 있습니까? 당신은 다음과 같이 확인할 수 있습니다 : 블로킹 모드에서

int flags = fcntl(fd, F_GETFD); 
if ((flags & O_NONBLOCK) == O_NONBLOCK) { 
    fprintf(stderr, "Yup, it's nonblocking"); 
} 
else { 
    fprintf(stderr, "Nope, it's blocking."); 
} 

는 RECV 아직받을 것이없는 경우 EAGAIN errno를 설정 즉시 반환합니다.

+0

안녕하세요, 회신 해 주셔서 감사합니다. 나는 "차단하지 않습니다."라는 메시지를받습니다. 차단 모드가 아닌 것으로 설정하도록 권장합니까? 나는 코드를 완료하는 첫 번째 게시물을 완료했습니다 – user586832

3

EAGAIN은 비 블로킹 소켓에서 읽을 수있는 데이터가 없음을 의미합니다. 따라서 recv 호출을 다시 실행해야합니다.

프로그래밍 오류가 있음을 알리는 데 충분한 코드를 게시하지 않았지만 모든 것이 다시 연결되기 전에 연결을 닫으면 연결을 닫는 지 여부를 묻는 메시지가 표시 될 수 있습니까?

+0

안녕하세요, 내가 코드를 차단하고있는 것으로 보인다 코드를 완료했습니다 ... 또한 함수가 데이터를 기다리지 만 항상 -1을 받도록 루프를 설정하려고합니다. 나는 무엇을 시도 할 수 있는가? 당신의 도움을 주셔서 감사합니다!! – user586832

+0

당신 말이 맞아요. 소켓은 기본적으로 차단됩니다. 수신 제한 시간을 설정했지만 즉 setsockopt (c-> fd_get, SOL_SOCKET, SO_RCVTIMEO, & timeout, sizeof (timeout)); . recv에서 -1을 얻었 기 때문에 어떤 종류의 오류 (또는 시간 초과!)가 있었음을 의미합니다. 그런 다음 errno 변수를 확인해야합니다. – Matt

0

각 소켓 읽기 작업을 수행하기 전에 항상 poll() 또는 select()를 사용합니다. 또한

는 비 차단을위한 테스트 :

int flags = fcntl(fd, F_GETFL, 0); 
    if (flags & O_NONBLOCK) { 
    fprintf(stderr, "Yup, it's nonblocking"); 
    } else { 
    fprintf(stderr, "Nope, it's blocking."); 
    }