美文网首页
非阻塞connect和accept

非阻塞connect和accept

作者: 小怪兽狂殴奥特曼 | 来源:发表于2018-04-17 21:59 被阅读436次

    1 非阻塞connect

    1.1 阻塞模式与非阻塞

    调用connect会发起三次连接。

    阻塞模式下,connect的返回结果:

    • 发出syn分节后,对方没有收到对端的syn分节,这时会返回ETIMEOUT。超时时间大概在75秒左右。
    • 发出syn分节后,对方没有在监听指定的端口,便会回复RST。这时返回ECONNREFUSED。
    • 发出syn分节后,引发路由器一个ICMP目的不可达的错误。多次尝试后仍无法成功发送,这时会返回EHOSTUNREACH或者ENETUNREACH。

    非阻塞模式下,调用connect后会立刻返回EINPROGRESS,同时三次握手还在进行。

    1.2 非阻塞模式的实现

    int socfd = socket();
    //set non-blocking
    int ret = connect(sockfd, ...);
    if(ret < 0)
    {
        return -1;
    }
    if(errno == EINPRPGRESS)
    {
        fd_set rdset, wrset;
        FD_SET(sockfd, rdset);
        FD_SET(sockfd, wrset);
        ret = select(sockfd+1, &rdset, &wrset, NULL, timeout);
        if(FD_ISSET(sockfd, &wrset))
        {
            if(FD_ISSET(sockfd, rdset))
            {
                //清楚sock error
            }
            //成功连接
            return sockfd.
        }
    }
    

    1.3 非阻塞connect的意义

    非阻塞connect的意义在于提高并发度。阻塞connect下,完成一个三次握手需要耗费一个RTT时间。RTT时间波动很大。从局域网内的几时毫秒到广域网的几十秒。阻塞模式下,进程被connect阻塞住,什么都干不了。非阻塞下,我们可以让select或者epoll来监听listenfd,直到完成三次连接再继续进行数据的手法。

    2 非阻塞accept

    2.1 非阻塞accept的实现

    int sockfd = socket();
    //set non-blocking
    bind()
    fd_set rdset;
    FD_SET(sockfd, &rdset);
    while(1)
    {
        int ret = select(sockfd+1, &rdset, NULL, NULL, timeout);
        if(ret < 0)
        {
            // err log
        }
        if(errno == EPROTO || ...)
        {
            continue;
        }
        int accept(sockfd,...);
    }
    

    2.2 注意点

    完成三次连接后,accept之前,select为可读,这个时候如果对端关闭连接,accept这个关闭的sockfd会阻塞。

    所以select返回后,accept前,总是忽略EWOULDBLOCK和ECONNABORTED、EPROTO、EINTR。

    2.3 非阻塞accept的意义

    非阻塞accept的意义同样在于提高并发度。

    相关文章

      网友评论

          本文标题:非阻塞connect和accept

          本文链接:https://www.haomeiwen.com/subject/csfmkftx.html