poll()返回-1,但在C ++中为errno 0

时间:2017-08-07 01:21:53

标签: c++ sockets

这个程序是代理服务器。 我用了poll()。当收到代理请求时,我会创建两个非阻塞套接字并连接并检查超时。

从poll()返回-1,在step3之后。 (连接,错误== EINPROGRESS) 这一次,我用gdb检查了m_fds,这很正常。

这怎么可能?
如果可能,我可以忽略这个结果吗?

这是流程的摘要代码。

int result = -1;
int timeout_ms = 500;
std::vector<struct pollfd> m_fds;
m_fds.reserve(1024);
std::map<int, Session> m_sessions;
std::set<Session> closeSessions;

while (!isStop) {
    result = poll(&m_fds[0], m_fds.size(), timeout_ms);
    // check connection timeout
    for(Session s : m_sessions) {
        if (s->isTimeout()) {
            closeSessions.insert(s);
        }
    }
    for (Sessions s: closeSession) {
        m_sessions.erase(s->getSocket());
        struct pollfd* pfd = findFdPtr(s->getSocket());
        close(s->getSocket());
        pfds->fd = -1;
    }
    closeSessions.clear();
    std::vector<pollfd>::iterator it;
    for (it = m_fds.begin(); it != m_fds.end();) {
        if (it->fd == -1) {
            m_fds.erase(it);
        }
        else {
            ++it;
        }
    }
    // connect to proxy targets

    if (result < 0) {
        if (errno == EINTR) {
            continue;
        }
        // This break will stop the my program.
        // result < 0, errno == 0. what happen?
        printf("[errno:%d][err_msg:%s]\n", errno, strerror(errno));
        break;
    }

    if (result == 0) {
        continue;
    }

    for (size_t i = 0; i < m_fds.size(); i++) {
        // process something.
    }
}

这是一个代理序列。我跳过写异常。

Step.1)创建非阻塞套接字。

int sock = socket(PF_INET, SOCK_STREAM, 0);
int socket_option_value = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &socket_option_value,
        sizeof(socket_option_value)) < 0) {
    close(sock);
    return -1;
}

if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &socket_option_value,
        sizeof(socket_option_value)) < 0) {
    close(sock);
    return -1;
}

int isNonblocking = 1;
if (ioctl(sock, FIONBIO, &isNonblocking) != 0) {
    return -1;
}

Step.2)注册m_fds

struct pollfd serverFd;
serverFd.revents = 0;
serverFd.events = 0;
serverFd.fd = sock;
m_fds->push_back(serverFd);

步骤3)尝试连接

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(connectIp);
server_addr.sin_port = htons(connectPort);

int result = connect(m_socket, (struct sockaddr *) &server_addr,
        sizeof(server_addr));

// trying...
if (errno == EINPROGRESS) {
    // register POLLOUT in m_fds. (ex: pfd.events |= POLLOUT;)
    return 0;
}

if (result < 0) {
    // unregister POLLOUT in m_fds. (ex: pfd.events &= ~POLLOUT;)
    return -1;
}

// unregister POLLOUT in m_fds.
// register POLLIN in m_fds.

Step.4)检查连接。

int result = -1;
int optval = -1;
socklen_t optlen = sizeof(optval);

do {
    if (getsockopt(m_socket, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) {
        break;
    }

    if (optval != 0) {
        break;
    }

    result = 0;
}
while (false);

if (result < 0) {
    // remove pollfd in m_fds and close socket.
}
else {
    // unregister POLLOUT and register POLLIN
    // non-blocking -> blocking
    int isNonblocking = 0;
    ioctl(m_socket, FIONBIO, &isNonblocking) != 0) {
         // handling exception
    }
}

更新:
*如何处理连接超时。

对不起,我的总结能力不高。

0 个答案:

没有答案