• Linux IO模型漫谈(4) 非阻塞IO


    首先先说一下,阻塞IO会在哪些地方阻塞住呢?输入操作read, 输出操作write,接受请求操作accept,发送请求操作connect,这四个地方阻塞进程。

    非阻塞IO的模型图示在前面的章节有讲过,它和阻塞IO的最大区别就是:如果连接或者操作不能立即建立,那么连接的建立照样能发起,只是会返回一个错误信息。

    同样,先说明几个用到的函数和操作:

    1 fcntl函数

    其全名为”file control“。顾名思义,fcntl可以执行各种操作符控制操作。

    #include <fcntl.h>
    
    int fcntl(int fd, int cmd, .. /* int arg */)
    

    第一个参数fd是文件描述符

    第二个参数cmd是操作命令,比如设置套接字阻塞非阻塞的命令为F_SETFL, 设置套接字属主的命令为F_SETOWN

    第三个参数以后,是操作命令的参数。比如设置非阻塞IO型的F_SETFL的参数为O_NONBLOCK

    所以设置非阻塞IO的典型设置代码为:

    flags = flags | O_NONBLOCK;

    fcntl(fd, F_SETFL, flags);

    2 非阻塞IO返回的错误

    对于不能满足的非阻塞IO操作,System V会返回EAGAIN错误,而源自Berkeley的实现返回EWOULDBLOCK。大多数当前系统把这两个错误码定义为相同的值。

    对不能满足的非阻塞IO连接,系统会返回EINPROGRESS

    按照非阻塞的定义,我们只需要将cli做下面修改:

    3客户端代码

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    
    
    int main(int argc, char* argv[])
    {
        int socketfd, n;
        socketfd = socket(AF_INET, SOCK_STREAM, 0);
        fcntl(socketfd, F_SETFL, O_NONBLOCK);
        
        struct sockaddr_in serv_addr;
    		
        bzero((char *)&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(7777);
    
        for(;;) {
            if(n = connect(socketfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
                if(errno == EINPROGRESS) {
                    printf("EINPROGRESS\n");
                }
            } else {
                break;
            }
        }
    		
        write(socketfd, "client message", 14);
    		
        char buffer[256];
        bzero(buffer, 256);
        read(socketfd, buffer, 255);
    		
        printf("server return message:%s\r\n", buffer);
    		
        return 0;
    
    }
     

    运行方式:

    1 server不启动

    2 client启动,则会在connect这个地方进入无限循环。

     

    好吧,是不是觉得有问题?

    1 这种模型,客户端使用轮询不断调用IO操作,那么,CPU就会一直用于轮询,造成cpu的浪费。

    2 这种模型,代码量比阻塞的模型大很多

    所以这个模型实际上是很少使用的。

    实时了解作者更多技术文章,技术心得,请关注微信公众号“轩脉刃的刀光剑影”

    本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名叶剑峰(包含链接http://www.cnblogs.com/yjf512/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

  • 相关阅读:
    算法 quick sort
    非常多学ThinkPHP的新手会遇到的问题
    原创jQuery插件之图片自适应
    管理线程之向线程函数传递參数
    [LeetCode]94.Binary Tree Inorder Traversal
    数据库基本概念
    Eclipse4.4 安装java反编译插件Eclipse Class Decompiler
    广义线性模型
    代理模式
    多态之中的一个(继承和虚函数)
  • 原文地址:https://www.cnblogs.com/yjf512/p/2536005.html
Copyright © 2020-2023  润新知