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

简介:

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

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

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

1 fcntl函数

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

1
2
3
#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客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#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
  

运行方式:

1 server不启动

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

 

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

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

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

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





本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/06/05/2536005.html,如需转载请自行联系原作者

相关文章
|
2月前
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
98 0
|
2月前
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
105 1
Linux C/C++之IO多路复用(aio)
|
2月前
|
网络协议 前端开发 Java
网络协议与IO模型
网络协议与IO模型
112 4
网络协议与IO模型
|
2月前
|
开发者
什么是面向网络的IO模型?
【10月更文挑战第6天】什么是面向网络的IO模型?
23 3
|
2月前
|
数据挖掘 开发者
网络IO模型
【10月更文挑战第6天】网络IO模型
44 3
|
2月前
|
缓存 Java Linux
硬核图解网络IO模型!
硬核图解网络IO模型!
|
2月前
|
数据挖掘 开发者
网络IO模型如何选择?
网络IO模型如何选择?【10月更文挑战第5天】
22 2
|
2月前
|
数据库
同步IO模型是一种常见的编程模型
【10月更文挑战第5天】同步IO模型是一种常见的编程模型
23 2
|
2月前
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
34 0
Linux C/C++之IO多路复用(poll,epoll)
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
下一篇
DataWorks