硬核图解网络IO模型!

原创
ithorizon 7个月前 (10-11) 阅读数 22 #Linux

硬核图解网络IO模型

在网络编程中,IO(输入/输出)操作是不可避免的。无论是读取文件、接收网络数据还是写入数据,IO操作都是程序与外部世界交互的桥梁。网络IO模型是懂得网络编程核心原理的关键,本文将硬核图解网络IO模型,帮助读者深入懂得其工作原理。

1. IO模型概述

IO模型关键描述了程序在执行IO操作时的状态转换和执行流程。常见的IO模型有五种:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO和异步IO。

2. 阻塞IO

阻塞IO是传统IO模型,程序执行IO操作时,当前线程会阻塞,等待IO操作完成。以下是一个易懂的阻塞IO示例:

#include <stdio.h>

#include <unistd.h>

int main() {

int fd = open("example.txt", O_RDONLY);

if (fd == -1) {

perror("open");

return 1;

}

char buffer[1024];

ssize_t bytes_read = read(fd, buffer, sizeof(buffer));

if (bytes_read == -1) {

perror("read");

close(fd);

return 1;

}

printf("Read %ld bytes: %s ", bytes_read, buffer);

close(fd);

return 0;

}

在上述代码中,程序执行read操作时,如果文件内容不足1024字节,当前线程会阻塞,直到读取到足够的数据或出现失误。

3. 非阻塞IO

非阻塞IO允许程序在IO操作未完成时继续执行其他任务。以下是一个非阻塞IO示例:

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

int main() {

int fd = open("example.txt", O_RDONLY | O_NONBLOCK);

if (fd == -1) {

perror("open");

return 1;

}

char buffer[1024];

ssize_t bytes_read;

while ((bytes_read = read(fd, buffer, sizeof(buffer))) == -1 && errno == EAGAIN);

if (bytes_read == -1) {

perror("read");

close(fd);

return 1;

}

printf("Read %ld bytes: %s ", bytes_read, buffer);

close(fd);

return 0;

}

在上述代码中,通过设置O_NONBLOCK标志,read操作不会阻塞当前线程。如果IO操作未完成,read会返回-1,并设置errno为EAGAIN,程序可以继续执行其他任务。

4. IO多路复用

IO多路复用允许程序同时监听多个IO操作,当任何一个IO操作完成时,程序可以立即得到通知并处理。epoll是Linux系统中常用的IO多路复用机制。以下是一个使用epoll的IO多路复用示例:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/epoll.h>

#define PORT 8080

int main() {

int listen_fd = socket(AF_INET, SOCK_STREAM, 0);

if (listen_fd == -1) {

perror("socket");

return 1;

}

struct sockaddr_in server_addr;

memset(&server_addr, 0, sizeof(server_addr));

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(PORT);

server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {

perror("bind");

close(listen_fd);

return 1;

}

if (listen(listen_fd, 5) == -1) {

perror("listen");

close(listen_fd);

return 1;

}

int epoll_fd = epoll_create1(0);

if (epoll_fd == -1) {

perror("epoll_create1");

close(listen_fd);

return 1;

}

struct epoll_event event;

event.data.fd = listen_fd;

event.events = EPOLLIN | EPOLLET;

epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event);

struct sockaddr_in client_addr;

socklen_t client_addr_len = sizeof(client_addr);

int accept_fd;


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: Linux


热门