Linux非阻塞IO(四)非阻塞IO中connect的实现

我们为客户端的编写再做一些工作。

这次我们使用非阻塞IO实现connect函数。

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

非阻塞IO有以下用处:

1.将三次握手的处理过程生下来,处理其他事情。

2.使用这个同时建立多个连接。

3.实现超时connect功能,本节实现的connect就可以指定时间,超时后算作错误处理。

 

在阻塞IO中,调用connect后一般会阻塞,直到确定连接成功或者失败。

在Non-Blocking IO中,connect往往会立刻返回,此时connect就有两种结果。

一是连接成功

二是返回-1,errno置为EINPROGRESS,这种一般是因为网络延迟,所以连接不能马上建立,我们需要使用poll来监听sockfd。

所以接下来我们需要向poll注册sockfd的写事件。

《TCP/IP详解》第二卷指出以下的一些规则:

当连接建立时,sockfd可写。

当遇到错误时,sockfd既可读又可写。

我们设置一个超时时间,当poll返回时,如果sockfd可写,此时有两种情况:

一是连接确实建立成功

二是连接发生错误

我们需要某些手段辨别究竟是否发生了错误。

这里我们采用socket选项,检测的是SO_ERROR,代码如下:

int get_sockfd_error(int sockfd)
{
    int err;
    socklen_t socklen = sizeof(err);
    if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &socklen) == -1)
        ERR_EXIT("getsock_error  error");
    if (err == 0)
        return 0; //无错误
    else
        return err;
}

如果sockfd无错误,则返回0,否则返回错误代码。

 

在非阻塞connect的实现中,我们通常需要先把fd设置为非阻塞,最后再重新设置为阻塞。这样做,是为了满足阻塞与非阻塞的需求。

因为在阻塞IO中,有时候也会使用非阻塞connect。

 

实现代码如下:

int nonblocking_connect(int sockfd, const char *des_host, uint16_t des_port, int timeout)
{
    if(des_host == NULL)
    {
        fprintf(stderr, "des_host can not be NULL\n");
        exit(EXIT_FAILURE);
    }

    SAI servaddr;
    memset(&servaddr, 0, sizeof servaddr);
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(des_port);
    if(inet_aton(des_host, &servaddr.sin_addr) == 0)
    {
        //DNS
        //struct hostent *gethostbyname(const char *name);
        struct hostent *hp = gethostbyname(des_host);
        if(hp == NULL)
            ERR_EXIT("gethostbyname");
        servaddr.sin_addr = *(struct in_addr*)hp->h_addr;
    }

    //设置为非阻塞
    activate_nonblock(sockfd); 

    //connect会立刻返回
    int ret = connect(sockfd, (SA*)&servaddr, sizeof servaddr);
    if(ret == -1)
    {
        if(errno != EINPROGRESS) //连接失败
            ERR_EXIT("connect error");
        struct pollfd pfd[1];
        pfd[0].fd = sockfd;
        pfd[0].events = POLLOUT;

        ret = poll(pfd, 1, timeout);

        if(ret == 0)
        {
            errno = ETIMEDOUT;
            ret = -1; //连接超时,此时判定为失败
        }
        //sockfd可写,此时需要检查套接字选项,查看是否发生错误
        else if(ret == 1 && pfd[0].revents & (POLLOUT | POLLWRBAND))
        {
            int err;
            //检查sockfd错误
            if((err = get_sockfd_error(sockfd)))
            {
                errno = err;
                return -1;
            }
        }
    }

    //重新设置为阻塞
    deactivate_nonblock(sockfd);
    return ret;
}

 

读者可以自行测试。

 

下节使用非阻塞connect实现客户端。

时间: 2024-10-12 22:36:40

Linux非阻塞IO(四)非阻塞IO中connect的实现的相关文章

[Z] linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO

原文链接:http://blog.csdn.net/colzer/article/details/8169075 IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据

linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性).那么我们的应用程序对文件的读写就通过对描述符的读写完成. linux将内存分为内核区,用户区.l

简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分别是什么含义. 同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:异步的概念和同步相对.当一个异步过程

linux同步与异步、阻塞与非阻塞概念以及五种IO模型

1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分别是什么含义. 同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:异步的概念和同步相对.当一个异步过程

python(十)下:事件驱动与 阻塞IO、非阻塞IO、IO多路复用、异步IO

上节的问题: 协程:遇到IO操作就切换. 但什么时候切回去呢?怎么确定IO操作完了? 一.事件驱动模型介绍 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求 第三种就是协程.时间驱动的方式,一般普遍认为第(3)种方式是大多数网络服务器采用的方式 论事件驱动模型 在UI编程中,,常常要对鼠标点击进行相应,

IO模型之阻塞、非阻塞、IO多路复用、异步

参考 http://www.cnblogs.com/Anker/p/3254269.html 及网络编程卷1第6章 网络IO模型详细分析 常见的IO模型有阻塞.非阻塞.IO多路复用,异步.以一个生动形象的例子来说明这四个概念.周末我和女友去逛街,中午饿了,我们准备去吃饭.周末人多,吃饭需要排队,我和女友有以下几种方案: (1)我和女友点完餐后,不知道什么时候能做好,只好坐在餐厅里面等,直到做好,然后吃完才离开. 女友本想还和我一起逛街的,但是不知道饭能什么时候做好,只好和我一起在餐厅等,而不能去

11 非阻塞套接字与IO多路复用(进阶)

1.非阻塞套接字 第一部分 基本IO模型 1.普通套接字实现的服务端的缺陷 一次只能服务一个客户端! 2.普通套接字实现的服务端的瓶颈!!! accept阻塞! 在没有新的套接字来之前,不能处理已经建立连接的套接字的请求. recv 阻塞! 在没有接受到客户端请求数据之前, 不能与其他客户端建立连接! 3.普通服务器的IO模型 第二部分 非阻塞套接字 1.非阻塞套接字与普通套接字的区别 >>> import socket >>> server = socket.sock

阻塞IO、非阻塞IO、IO多路复用、同步IO、异步IO 的理论

同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wiki,就认为asynchronous IO和non-blocking IO是一个东西.这其实是因为不同的人的知识背景不同,并且在讨论这个问题的时候上下文(context)也不相同.所以,为了更好的回答这个问题,我先限定一下本文的上下文.本文讨论的背景是Linux环境下的ne

理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO

完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network IO. 一 概念说明 在进行解释之前,首先要说明几个概念:- 用户空间和内核空间- 进程切换- 进程的阻塞- 文件描述符- 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,

{python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块

阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 异步IO(Asynchronous I/O) 六 IO模型比较分析 七 selectors模块 一 IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能