Bootstrap

Linux下设置socket()中网络层的read()和write()状态为阻塞或非阻塞态

一、定义
阻塞模式:指的是当某个函数执行成功的条件当前不满足时,该函数会阻塞当前执行线程,程序执行流在超时时间到达或执行成功的条件满足后恢复继续执行。
非阻塞模式:即使某个函数执行成功的条件不满足,该函数也不会阻塞当前执行线程,而是立即返回,继续执行程序流。

二、如何将socket设置为非阻塞模式

无论是在Windows还是Linux,默认创建的socket都是阻塞模式的。

设置为非阻塞后,send会返回EAGAIN或者EWOULDBLOCK错误,此时可以调用select函数来监视何时可以发送数据。

1、第一种方式
在Linux上,可以通过使用fcntl函数或者ioctl函数给创建的socket增加O_NONBLOCK标志来将socket设置为非阻塞模式,示例代码如下:

使用fcntl函数来设置接收为非阻塞需要的头文件

#include <fcntl.h> 
 
#include<unistd.h>
在接收前调用,更改接收为非阻塞。

fcntl(sockfd,F_SETFL,O_NONBLOCK);
2、第二种方式
Linux上的socket函数也可以在创建时将socket设置为非阻塞模式

socket函数定义
 
int socket(int domain, int type, int protocol);

只要给type参数增加一个SOCK_NONBLOCK标志即可,例如:

int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
3、第三种方式
在Linux上利用accept函数返回的代表与客户端通信的socket也提供了一个扩展函数accept,直接将accept函数返回的socket设置为非阻塞的:

int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen);
int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen, int flags);
只需要将accept函数最后一个参数设置为SOCK_NONBLOCK即可。如下:

socklen_t addrlen = sizeof(clientaddr);
int clientfd = accept4(listenfd, &clientaddr, &addrlen, SOCK_NONBLOCK);

;