基于非阻塞I/O模型的服务器回射程序设计代码实现
时间: 2023-08-14 11:04:33 浏览: 158
以下是一个基于非阻塞 I/O 模型的服务器回射程序的代码实现,使用 C 语言和 Linux 系统的 epoll 实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#define MAX_EVENTS 1024
#define PORT 8888
int main() {
// 创建 socket,并设置为非阻塞模式
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
fcntl(listenfd, F_SETFL, O_NONBLOCK);
// 绑定 IP 地址和端口号
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
// 监听 socket
if (listen(listenfd, SOMAXCONN) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 创建一个事件循环,并注册监听 socket 的读事件
int epfd = epoll_create(1);
if (epfd < 0) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = listenfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) {
perror("epoll_ctl");
exit(EXIT_FAILURE);
}
struct epoll_event events[MAX_EVENTS];
// 在事件循环中,处理监听 socket 的读事件和连接 socket 的读写事件
while (1) {
int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int i = 0; i < nfds; i++) {
if (events[i].data.fd == listenfd) {
// 有新的连接
while (1) {
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
int connfd = accept(listenfd, (struct sockaddr*)&clientaddr, &clientaddrlen);
if (connfd < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
} else {
perror("accept");
break;
}
}
fcntl(connfd, F_SETFL, O_NONBLOCK);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = connfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev) < 0) {
perror("epoll_ctl");
exit(EXIT_FAILURE);
}
}
} else {
// 处理连接的读写事件
int connfd = events[i].data.fd;
char buf[1024];
while (1) {
int n = read(connfd, buf, sizeof(buf));
if (n < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
} else {
perror("read");
if (epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, &ev) < 0) {
perror("epoll_ctl");
exit(EXIT_FAILURE);
}
close(connfd);
break;
}
} else if (n == 0) {
if (epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, &ev) < 0) {
perror("epoll_ctl");
exit(EXIT_FAILURE);
}
close(connfd);
break;
} else {
write(connfd, buf, n);
}
}
}
}
}
// 关闭 socket
close(listenfd);
return 0;
}
```
上面的代码实现了一个简单的服务器回射程序,可以同时处理多个连接的读写事件。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)