
Unix/Linux 编程:网络编程之 epoll与Reactor
发布日期:2021-05-07 23:34:49
浏览次数:23
分类:精选文章
本文共 4736 字,大约阅读时间需要 15 分钟。
??????????epoll????IO???????????????????????????????if???????????????????????????Reactor?????????epoll???????????????????????????????????????????????????
???????epoll??????
#include#include #include #include #include #include #include #include #include #include #include #include #define BUFFER_LENGTH 1024 #define EVENT_SIZE 1024 struct sockitem { int sockfd; int (*callback)(int events, void* arg); char recvbuffer[BUFFER_LENGTH]; char sendbuffer[BUFFER_LENGTH]; }; struct reactor { int epollfd; struct epoll_event events[EVENT_SIZE]; }; struct reactor *g_eventloop = NULL; int recv_cb(int events, void* arg) { if (!(events & EPOLLIN) || arg == NULL) { return -1; } struct sockitem* si = (struct sockitem*)arg; int clientfd = si->sockfd; int epoll_fd = g_eventloop->epollfd; char buffer[BUFFER_LENGTH] = {0}; struct epoll_event ev; int ret = recv(clientfd, buffer, BUFFER_LENGTH, 0); if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { printf("read all data\n"); } close(clientfd); ev.events = EPOLLIN | EPOLLET; //ev->data.fd = clientfd; ev.data.ptr = NULL; free(si); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, clientfd, &ev); } else if (ret == 0) { printf("disconnect clientfd:%d\n", clientfd); close(clientfd); ev.events = EPOLLIN | EPOLLET; //ev->data.fd = clientfd; ev.data.ptr = NULL; free(si); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, clientfd, &ev); return 0; } else { printf("Recv: %s, %d Bytes\n", buffer, ret); ev.events = EPOLLOUT | EPOLLET; si->sockfd = clientfd; si->callback = send_cb; ev.data.ptr = si; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, clientfd, &ev); return 0; } } int send_cb(int events, void* arg) { if (!(events & EPOLLOUT) || arg == NULL) { return -1; } struct sockitem* si = (struct sockitem*)arg; int clientfd = si->sockfd; int epoll_fd = g_eventloop->epollfd; if (send(clientfd, "Hello, you are connected!\n", 26, 0) == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return 0; } perror("send error"); close(clientfd); return -1; } ev.events = EPOLLIN | EPOLLET; si->callback = recv_cb; ev.data.ptr = si; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, clientfd, &ev); return 0; } int accept_cb(int events, void* arg) { if (!(events & EPOLLIN) || arg == NULL) { return -1; } struct sockitem* psi = (struct sockitem*)arg; int epoll_fd = g_eventloop->epollfd; int sockfd = psi->sockfd; struct sockaddr_in client_addr; struct epoll_event ev; memset(&client_addr, 0, sizeof(struct sockaddr_in)); socklen_t client_len = sizeof(client_addr); int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len); if (clientfd <= 0) { return -1; } char str[INET_ADDRSTRLEN] = {0}; struct sockitem* si = (struct sockitem*)malloc(sizeof(struct sockitem)); si->sockfd = clientfd; si->callback = recv_cb; printf("received from %s at port:%d, sockfd:%d, clientfd:%d\n", inet_ntop(AF_INET, &client_addr.sin_addr, str, sizeof(str)), ntohs(client_addr.sin_port), sockfd, clientfd); ev.events = EPOLLIN | EPOLLET; ev.data.ptr = si; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, clientfd, &ev); return 0; } int main(int argc, char* argv[]) { if (argc < 2) { printf("parameter error!\n"); return EXIT_FAILURE; } int port = atoi(argv[1]); int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { return -1; } struct sockaddr_in addr; memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) { exit(EXIT_FAILURE); } printf("start server and wait for connection...\n"); if (listen(sockfd, 5) < 0) { exit(EXIT_FAILURE); } g_eventloop = (struct reactor*)malloc(sizeof(struct reactor)); g_eventloop->epollfd = epoll_create(1); struct epoll_event ev; ev.events = EPOLLIN; struct sockitem* si = (struct sockitem*)malloc(sizeof(struct sockitem)); si->sockfd = sockfd; si->callback = accept_cb; ev.data.ptr = si; epoll_ctl(g_eventloop->epollfd, EPOLL_CTL_ADD, sockfd, &ev); while (1) { int nready = epoll_wait(g_eventloop->epollfd, g_eventloop->events, EVENT_SIZE, -1); if (nready < -1) { break; } int i = 0; for (i = 0; i < nready; i++) { if (g_eventloop->events[i].events & EPOLLIN) { struct sockitem* si = (struct sockitem*)g_eventloop->events[i].data.ptr; if (si && si->callback) { si->callback(g_eventloop->events[i].events, si); } } if (g_eventloop->events[i].events & EPOLLOUT) { struct sockitem* si = (struct sockitem*)g_eventloop->events[i].data.ptr; if (si && si->callback) { si->callback(g_eventloop->events[i].events, si); } } } } close(sockfd); exit(EXIT_SUCCESS); }
???????????epoll_wait????????recv_cb?send_cb???????epoll?????????????????reactor???????????????????????????????????????????
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2025年05月02日 02时50分08秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Elasticsearch入门教程(Elasticsearch7,linux)
2025-03-29
ElasticSearch设置字段的keyword属性
2025-03-29
Elasticsearch面试题
2025-03-29
element 如何使用自定义icon图标
2025-03-29
element-plus修改主题颜色
2025-03-29
element-ui:el-input输入数字-整数和小数
2025-03-29
ElementUI-el-progress改变进度条颜色跟文字样式
2025-03-29
ELK应用日志收集实战
2025-03-29
elTable火狐浏览器换行
2025-03-29
15个Python数据处理技巧(非常详细)零基础入门到精通,收藏这一篇就够了
2025-03-29
0基础成功转行网络安全工程师,年薪30W+,经验总结都在这(建议收藏)
2025-03-29
100个电脑常用组合键大全(非常详细)零基础入门到精通,收藏这篇就够了
2025-03-29
10个程序员可以接私活的平台
2025-03-29
10条sql语句优化的建议
2025-03-29