在五种IO模型中有提到在Linux中,默认所有的套接字都是阻塞的。所以要实现非阻塞的套接字,就要执行特定的系统调用来实现。
fcntl
函数原型:
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
参数说明:
fd:表示对哪个文件描述符进行操作
cmd:表示对文件描述符进行什么操作
arg:根据操作的不同而又不同的取值
函数功能:该函数的功能有很多,对应的cmd取值也有很多,但这里实现的只是将文件描述符设置为非阻塞。所以只介绍该部分的功能。
cmd = F_GETFL:获取文件状态标记,此时状态标记由返回值带回,参数arg为空。返回值为负数,说明获取失败。
cmd = F_SETFL:设置文件状态标记,此时新设置的文件状态标记由参数arg标识,返回值表示设置成功与否。
上述的文件状态其实是一个位图。不同的比特位表示不同的状态。不同的状态信息由不同的宏来标识。不同的宏之代表的数字之间只有一个比特位不同。O_NONBLOCK表示的就是文件的非阻塞状态。
下面通过将标准输入设置为非阻塞来使用该函数:
如果标准输入为阻塞状态,在对标准输入进行读取数据时,如果没有数据,此时进程就会被挂起等待,阻塞在相应的系统调用处,且该系统调用不返回。
如果标准输入为非阻塞状态,在对其进行读取数据时,如果没有数据,此时进程不会被挂起,而是系统调用返回后,进程可以做其他的事情。
首先编写将文件描述符设置为非阻塞的函数:
void SetNoBlock(int fd)
{
//首先利用fcntl函数获取文件描述符的文件标记状态
int flag = fcntl(fd,F_GETFL);
if(flag < 0)
{
perror("fcntl");
return;
}
//设置文件描述符的标记状态,在原有的基础上再加一个非阻塞的标记状态
fcntl(fd,F_SETFL,flag | O_NONBLOCK);
return;
}
通过将标准输入设置为阻塞和非阻塞来进行演示(标准输入默认是阻塞的):
int main()
{
SetNoBlock(0);//将标准输入设置为非阻塞的状态
char buf[1024] = {0};
while(1)
{
//注意:此处应使用int类型的变量来接收s,因为当