当前位置: 首页 > 知识库问答 >
问题:

读取套接字:eAgain:资源暂时不可用

汪深
2023-03-14
  • 创建套接字
  • 使其非阻塞
  • 呼叫连接
  • 按预期返回-1和errno EINPROGRESS
  • 调用select
  • 返回>0,因此已建立连接
  • 再次阻塞套接字

此部件的代码如下:

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;
}

共有1个答案

姚正真
2023-03-14

eAgain并不表示您已断开连接,它只是表示“现在没有可读的内容,稍后再试”。

您可以使用fcntl(2)取消设置O_nonblock(使read等待,直到有可用的内容),或者在调用read之前,使用select(2)等套接字。

编辑:现在您已经添加了更多代码,我可以看到您正在为套接字设置so_rcvtimeo。这会导致阻塞的read返回eairy(因此,如果不希望发生这种情况,只需保留SO_RCVTIMEO)。

 类似资料:
  • 我正在实现一个UNIX域套接字进程间通信代码,在试图从套接字读取时,我随机地碰到了这个错误--“errno 11:资源暂时不可用”。我使用MSG_PEEK从套接字读取字节数,并为接收缓冲区分配字节数,并读取实际数据。 套接字是一个阻塞套接字,我没有任何非阻塞的代码(总之,接受/读/写)。在阻塞套接字读取中,有什么可能导致这种情况的指针吗?在MSG_PEEK的手册页中,当socket标记为非阻塞时,

  • 我想用pywebkitgtk捕获网页。我已经在那台机器上安装了X org服务器,除了一些例外情况外,还启动了X服务器,但是X服务器正在运行。问题是我不能从X unix套接字中读取任何数据,它是path=@“/tmp/.x11-unix/x0”的PF_FILE类型,recvfrom正在抛出EAGAIN(资源暂时不可用)错误,对该套接字的轮询经常超时,没有任何数据,下面是跟踪日志,在其中我们可以找到成

  • 我在C中使用tcp套接字服务器和客户端。使用AF_INET、SOCK_STREAM和IPPROTO_TCP 在sock send()命令上有一个可能导致“资源暂时不可用”的帖子,其中Davide Berra说 这是因为您使用的是非阻塞套接字,并且输出缓冲区已满。 从send()手册页

  • 我使用tcpdump从客户端捕获数据包,每个数据包都是分段到最大1448字节的数据,但是head只有5字节,为什么我可以成功读取head,但是下面的data recv()操作又会返回ee?当数据已经到达recv缓冲区时,recv是否可能返回EAGAIN?在我看来,我可以读取前5个字节,所以必须有更多的数据在recv缓冲区读取。 可能与TCP/IP协议栈中的组装过程有关。代码如下所示,每个pdu r

  • 我有一个伪终端从机,它给我一个资源暂时不可用的读/写错误(11)。我一直无法解决这个问题,但直到一周前我还不知道任何事情。所以,我可能漏掉了一些明显的东西。 根据我所了解的情况,这可能是由对非阻塞PTY调用引起的。但是,当我检查从pty的I之后的时,该值显示它是一个阻塞文件描述符。 我甚至尝试将视为非阻塞文件,使用来确定它何时就绪。但是,它只是每次都超时。 那么,如果设置为blocking,为什么