2011-01-24 32 views
2

我實現了一個套接字客戶端,通過HTTP與RTSP進行通信,從攝像頭獲取視頻。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; 

    } 

難道是一個超時問題?或堆棧問題?我如何解決它?

在此先感謝您的幫助。最好的祝福。

克里斯蒂娜

+1

什麼名字`EAGAIN`建議你應該嘗試一下呢? – 2011-01-24 01:21:16

回答

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 2011-01-25 11:11:28

3

EAGAIN表示沒有數據可用於在非阻塞套接字上讀取。所以,你應該再次運行recv調用。

你實際上沒有發佈足夠的代碼來暗示有編程錯誤,但是我能否問一下,當你檢測到連接關閉時,你還關閉了你的端點,並且在重新建立所有事情之前?

+0

你好,我已經完成了代碼似乎代碼阻塞...我也試圖設置一個循環,所以函數等待數據,但它總是收到-1。我可以嘗試什麼?謝謝你的幫助!! – user586832 2011-01-25 11:14:10

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."); 
    }