2011-01-24 94 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."); 
    }