传统IO模型
阻塞式IO模型图
阻塞式IO使用案例
下面是一个利用传统IO模型实现的简易http服务器
代码如下:
#include <stdio.h>//标准输入输出头文件,定义了一些输入输出函数,比如 printf, scanf 等。
#include <stdlib.h>//标准库头文件,定义了一些库函数,比如 malloc, exit 等。
#include <string.h>//字符串头文件,定义了一些字符串操作函数,比如 strlen, memset 等。
#include <unistd.h>//Unix 标准函数头文件,定义了一些常用的函数,比如 read, write 等。
#include <sys/socket.h>//socket 函数头文件,定义了一些 socket 函数,比如 socket, bind, listen, accept 等。
#include <netinet/in.h>//Internet 地址头文件,定义了一些 Internet 地址结构,比如 sockaddr_in 等。
#include <arpa/inet.h>//Internet 地址转换头文件,定义了一些 Internet 地址转换函数,比如 inet_ntop 等。
#define PORT 8080 //连接的端口号
#define BACKLOG 5 //连接队列长度
#define BUFFERSIZE 4089//缓冲区大小
int main() {
int listenfd, connfd;
struct sockaddr_in serv_addr, client_addr;
char buffer[BUFFERSIZE];
socklen_t addr_size;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT);
if (bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) {
perror("绑定失败");
exit(EXIT_FAILURE);
}
if (listen(listenfd, BACKLOG) == -1) {
perror("监听失败");
exit(EXIT_FAILURE);
}
addr_size = sizeof(client_addr);
printf("服务器启动, 监听端口 %d\n", PORT);
while (1) {
connfd = accept(listenfd, (struct sockaddr *) &client_addr, &addr_size);
int port = ntohs(client_addr.sin_port);
struct in_addr in = client_addr.sin_addr;
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &in, str, sizeof(str));
printf("客户端信息: ip:port = %s:%d\n", str, port);
if (connfd == -1) {
perror("accept失败");
break;
}
ssize_t n = read(connfd, buffer, BUFFERSIZE);
if (n > 0) {
buffer[n] = '\0';
printf("收到的请求信息:\n%s\n", buffer);
char *response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html;charset=utf-8\r\n"
"\r\n"
"<html><body><h1>Hello, World!</h1></body></html>\r\n";
write(connfd, response, strlen(response));
}
close(connfd);
}
close(listenfd);
return 0;
}
代码主要逻辑
代码中,服务器的网络通信是基于阻塞式的套接字(socket)来实现的。首先通过socket函数创建一个套接字,然后通过bind函数将套接字与服务器的地址信息关联起来。随后,调用listen函数以使该套接字进入监听状态。
当有客户端连接到服务器时,服务器调用accept函数将返回一个已连接的套接字,使用read函数从已连接的套接字读取客户端的请求信息。如果读取到了数据,服务器使用write函数向客户端发送一个响应。然后,服务器关闭已连接的套接字,并回到监听状态,等待下一个客户端的连接。
该http服务器是一个阻塞式服务器,因为在读取或写入数据时,它始终处于阻塞状态,直到数据到达或操作完成。
运行截图