Linux 非阻塞网络IO模式

非阻塞网络IO模式介绍

当用户线程发起一个 read 操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个 error 时,它就知道数据还没有准备好,于是它可以再次发送 read 操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。

所以事实上,在非阻塞 IO 模型中,用户线程需要不断地询问内核数据是否就绪,也就 说非阻塞 IO 不会交出 CPU,而会一直占用 CPU。

Linux 非阻塞网络IO模式_第1张图片

设置非阻塞常用方式:

方式一: 创建 socket 时指定

int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);

方式二: 在使用前通过如下方式设定

fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);

方式一 demo

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUFF_SIZE 1024

int main(void)
{
        int server_sockfd;
        int client_sockfd;
        char ch;
        int ret;
        int recv_len;
        char buff[BUFF_SIZE];
        //用于 UNIX 系统内部通信的地址, struct sockaddr_un
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;

        int client_addr_len =sizeof(struct sockaddr_in);
        server_sockfd = socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0);
        // 设置服务器地址
        server_addr.sin_family = AF_INET;               //地址的域,相当于地址的类型,AF_UNIX 表示地址位于 UNIX 系统内部
        server_addr.sin_addr.s_addr = INADDR_ANY;       //inet_addr("10.10.0.9");
        server_addr.sin_port = htons(9000);
        // 绑定该套接字,使得该套接字和对应的系统套接字文件关联起来。
        ret = bind(server_sockfd, (struct sockaddr*)&server_addr,sizeof(server_addr));

        if (ret == -1) {
                perror("bind");
                exit(1);
        }
        // 创建套接字队列, 保存进入该服务器的客户端请求。
        // ret = listen(server_sockfd, 5);
        // 循环处理客户端请求
        while (1) {
                printf("server waiting\n");
                // 等待并接收客户端请求
                //client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_addr, &client_addr_len);
                recv_len = recvfrom(server_sockfd, buff, sizeof(buff) , 0,(struct sockaddr*)&client_addr, &client_addr_len);
                if (recv_len < 0) {
                        if(errno == EAGAIN ||errno == EWOULDBLOCK){
                                sleep(2);
                                continue;
                        }
                        perror("recvfrom");
                        exit(errno);
                }
                printf("received: %s\n", buff);
        }
        close(server_sockfd);
        return 0;
}

Linux 非阻塞网络IO模式_第2张图片
方式二 demo

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUFF_SIZE 1024

int main(void)
{
        int server_sockfd;
        int client_sockfd;
        char ch;
        int ret;
        int recv_len;
        char buff[BUFF_SIZE];
        //用于 UNIX 系统内部通信的地址, struct sockaddr_un
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;

        int client_addr_len =sizeof(struct sockaddr_in);
        server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        // 设置服务器地址
        server_addr.sin_family = AF_INET;               //地址的域,相当于地址的类型,AF_UNIX 表示地址位于 UNIX 系统内部
        server_addr.sin_addr.s_addr = INADDR_ANY;       //inet_addr("10.10.0.9");
        server_addr.sin_port = htons(9000);
        // 绑定该套接字,使得该套接字和对应的系统套接字文件关联起来。
        ret = bind(server_sockfd, (struct sockaddr*)&server_addr,sizeof(server_addr));

        if (ret == -1) {
                perror("bind");
                exit(1);
        }
        // 创建套接字队列, 保存进入该服务器的客户端请求。
        // ret = listen(server_sockfd, 5);


        fcntl(server_sockfd, F_SETFL, fcntl(server_sockfd, F_GETFL, 0) | O_NONBLOCK);
        // 循环处理客户端请求
        while (1) {
                printf("server waiting\n");
                // 等待并接收客户端请求
                //client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_addr, &client_addr_len);
                recv_len = recvfrom(server_sockfd, buff, sizeof(buff) , 0,(struct sockaddr*)&client_addr, &client_addr_len);
                if (recv_len < 0) {
                        if(errno == EAGAIN ||errno == EWOULDBLOCK){
                                sleep(2);
                                continue;
                        }
                        perror("recvfrom");
                        exit(errno);
                }
                printf("received: %s\n", buff);
        }
        close(server_sockfd);
        return 0;
}

Linux 非阻塞网络IO模式_第3张图片

你可能感兴趣的:(linux基础,linux,网络)