非阻塞connect的实现

需要非阻塞connec的几种情况:
1.三路握手需要时间,这个要视具体的网络情况而定。当然也有可能失败。在三路握手的时候我们并不需要在原地等待三路握手的完成,可以用这些时间来完成其它事情,然后当这些事情完成后,再去检测连接是否建立(也就是三路握手是否完成)。
2.可以用这种技术来同时建立多个连接。(WEB浏览器中很常用)。
3.connect超时需要很长时间才会通知,如果我们认为超过0.1秒以后就算超时(不管它是不是真的超时),这是就可以使用非阻塞式I/O结合 select来完成。
// 设置套接字非阻塞!
int SetNonBlocking(int fd)
{
    int old_option = fcntl(fd,F_GETFL);
    int new_option = old_option | O_NONBLOCK;
    fcntl(fd,F_SETFL,new_option);
    return old_option;
}
int ConnectNonBlocking(int fd, const sockaddr *addr, socklen_t addrlen, int nsec)
{
    int oldflag = SetNonBlocking(fd);

    int ret = -1;

    if((ret = connect(fd,addr,addrlen)) < 0)
    {
        if(errno != EINPROGRESS) // 发生了其他错误
        {
            return -1;
        }
    }

    // errno == EINPROGRESS的情况继续往下执行

    if(ret == 0)
    {
        fcntl(fd,F_SETFL,oldflag);
        return 0; //连接成功
    }

    fd_set rset,wset;

    FD_ZERO(&rset);

    FD_SET(fd,&rset);

    wset =rset;

    timeval time_out;
    time_out.tv_sec = nsec;
    time_out.tv_usec = 0;

    // 超时时间设置
    timeval* ptime_out = 0;

    if(nsec > 0)
    {
        ptime_out = &time_out;
    }

    if((ret = select(fd+1,&rset,&wset,0,ptime_out)) == 0)
    {
        // 发生超时
        close(fd);
        errno = ETIMEDOUT;
        return -1;
    }

    // 判断连接是否成功
    if(FD_ISSET(fd,&rset) || FD_ISSET(fd,&wset))
    {
        int err = 0;
        int len = sizeof(err);

        // 获取错误
        if(getsockopt(fd,SOL_SOCKET,SO_ERROR,&err,&len) < 0) 
        {
            // 出错
            close(fd);
            return -1;
        }

        if(err)
        {
            // 出错
            close(fd);
            errno = err;
            return -1;
        }
    }
    else
    {
        printf("select error:socketfd not set!\n");
        exit(-1);
    }

    // 连接成功!
    fcntl(fd,F_SETFL,oldflag);
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值