2011-01-24 10 views
2

カメラからビデオを取得するために、ソケットクライアントがHTTP経由でRTSPを使用してIPカメラと通信することを暗示しました。EAGAIN on recv()

カメラとの通信を確立するには、まずHTTP-GETトンネルを設定してから、RTSPコマンドを送信する必要があります。カメラが接続を失うと、プログラムはトンネルハンドラを終了し、スレッドを終了し、プロセスがメイン関数に戻ると、通信を開始します(トレッドを開始するなど)。

再接続時:http-getトンネルがokに設定されています。ソケットが接続して「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はまだ受け取るために何もない場合は、errnoにEAGAINが設定すぐに戻ります。

+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."); 
    } 
関連する問題