热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一个epoll的ET模式下的非阻塞的服务端小用例

后续知识会进行整理代码**echoserver*Time:2021-12-02*Author:LH*code:--utf8--*#ifdef____Win32#els

后续知识会进行整理

代码

/** echo server
* Time: 2021-12-02
* Author: LH
* code: --utf8--
*/
#ifdef ____Win32
#else
/* network io */
#include
#include
#include
#include
#include /* linux */
#include
#include
#include /* C */
#include
#include #define SERVERPORT 3119int main() {/** Create listening sockets*/int listenfd &#61; socket(AF_INET, SOCK_STREAM, 0);if (listenfd &#61;&#61; -1) {printf("socket error \n");return -1;}/* Set reuse IP and port number */int on &#61; 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on));/* Set feizuse */int oldSocketFlag &#61; fcntl(listenfd, F_GETFL, 0);int newSocketFlag &#61; oldSocketFlag | O_NONBLOCK;if (fcntl(listenfd, F_SETFL, newSocketFlag) &#61;&#61; -1) {close(listenfd);printf("fcntl error \n");return -1;}/* Initializing the server */struct sockaddr_in bindaddr;bindaddr.sin_family &#61; AF_INET;bindaddr.sin_addr.s_addr &#61; htonl(INADDR_ANY);bindaddr.sin_port &#61; htons(SERVERPORT);if (bind(listenfd, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) &#61;&#61; -1) {printf("bind error \n");close(listenfd);return -1;} /* Start Listening */if (listen(listenfd, SOMAXCONN) &#61;&#61; -1) {printf("listen error \n");close(listenfd);return -1; }/* create epoll */int epollfd &#61; epoll_create(1);if (epollfd &#61;&#61; -1) {printf("epoll_create error \n");close(listenfd);return -1; }/** struct epoll_event {* uint32_t events; fd event flags to be monitored* epoll_data_t data; User-defined data* }* typedef union epoll_data {* void *prt;* int fd;* uint32_t u32;* uint64_t u64;* }*/struct epoll_event listen_fd_event;listen_fd_event.data.fd &#61; listenfd;listen_fd_event.events &#61; EPOLLIN; /**The default is LT mode, * where a fixed number of bytes are charged at once according to the* service until they are collected *//**ET mode, when the readable event is triggered, the data on the * socket must be collected at once to feel, must be the village to * call the recv function until the recv error, the error code is EWOULDBLOCK*/// listen_fd_event.events |&#61; EPOLLET; /* start ET *//* Bind the listening socket to epollfd */if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &listen_fd_event) &#61;&#61; -1) {printf("epoll_ctl error \n");close(listenfd);return -1; }int n;while(1) {struct epoll_event epoll_events[1024];/* Returns the number of fd&#39;s with time */n &#61; epoll_wait(epollfd, epoll_events, 1024, 1000);if (n < 0) {/* Interrupted by signal */if (errno &#61;&#61; EINTR) continue;break;}else if (n &#61;&#61; 0) {/* Timeout, continue */continue;}for (size_t i &#61; 0; i < n; &#43;&#43; i) {/* Event Readable */if (epoll_events[i].events & EPOLLIN) {if (epoll_events[i].data.fd &#61;&#61; listenfd) {printf("a new client is connect! \n");/* Listening to sockets and receiving new connections */struct sockaddr_in clientaddr;socklen_t clientaddrlen &#61; sizeof(clientaddr);int clientfd &#61; accept(listenfd, (struct sockaddr *) &clientaddr, &clientaddrlen);if (clientfd !&#61; -1) {/* Set feizuse */int oldSocketFlag &#61; fcntl(clientfd, F_GETFL, 0);int newSocketFlag &#61; oldSocketFlag | O_NONBLOCK;if (fcntl(clientfd, F_SETFL, newSocketFlag) &#61;&#61; -1) {close(clientfd);printf("set client to nonblocking error \n");}else {/** struct epoll_event {* uint32_t events; fd event flags to be monitored* epoll_data_t data; User-defined data* }*/struct epoll_event client_fd_event;client_fd_event.data.fd &#61; clientfd;/* Listening to both read and write events */client_fd_event.events &#61; EPOLLIN | EPOLLOUT; client_fd_event.events |&#61; EPOLLET;/* Add to epollfd */if (epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &client_fd_event) !&#61; -1) {// printf("new client accepted, clientfd: %d \n", clientfd); }else {printf("add client fd to epollfd error \n");close(clientfd);}}}}else {printf("client fd: %d recv data \n", epoll_events[i].data.fd);char recvbuf[1024] &#61; { 0 };/* Receive 1 byte at a time */int m &#61; recv(epoll_events[i].data.fd, &recvbuf, 1024, 0);if (m &#61;&#61; 0) {/* The other end closes the connection and removes the clienfd from the epollfd */if (epoll_ctl(epollfd, EPOLL_CTL_DEL, epoll_events[i].data.fd, NULL) !&#61; -1) {printf("client disconnected clientfd: %d \n", epoll_events[i].data.fd);}close(epoll_events[i].data.fd);}else if (m < 0) {/* error */if (errno !&#61; EWOULDBLOCK && errno !&#61; EINTR) {/* The other end closes the connection and removes the clienfd from the epollfd */if (epoll_ctl(epollfd, EPOLL_CTL_DEL, epoll_events[i].data.fd, NULL) !&#61; -1) {printf("client disconnected clientfd: %d \n", epoll_events[i].data.fd);}close(epoll_events[i].data.fd);}}else {/* normal */printf("recv from client: %d,%s", epoll_events[i].data.fd, recvbuf);struct epoll_event client_fd_event;client_fd_event.data.fd &#61; epoll_events[i].data.fd;/* Register the writeable event to clientfd again *//**In ET mode, the writable event will not be triggered all the time,* he will only trigger once and register again after the trigger is * completed, and the writable event will continue to trigger only * when the writable event is monitored. LT is repeatedly triggered * by writable events. After a writable event is triggered, if it * is no longer needed, the registration of the writable event should* be removed immediately*/client_fd_event.events &#61; EPOLLIN | EPOLLOUT | EPOLLET;if (epoll_ctl(epollfd, EPOLL_CTL_MOD, epoll_events[i].data.fd, &client_fd_event) !&#61; -1) {// printf("epoll_ctl successfully, mode: EPOLL_CTL_MOD, clientfd: %d \n", epoll_events[i].data.fd);}else {printf("epoll_ctl failure, mode: EPOLL_CTL_MOD, clientfd: %d \n", epoll_events[i].data.fd);}}}}/* Listening to write events */else if (epoll_events[i].events & EPOLLOUT) {/* Handle only write events for client fd */if (epoll_events[i].data.fd !&#61; listenfd) {/* print result */// printf("EPOLLOUT Triggered, clientfd: %d \n", epoll_events[i].data.fd);}}else if (epoll_events[i].events & EPOLLERR) {// TODOprintf("epoll error! \n");}}} close(listenfd);return 0;
}
#endif

测试

> gcc -g -o epoll_server epoll_server.c
> ./epoll_server
a new client is connect!
client fd: 5 recv data
recv from client: 5,asdh
client fd: 5 recv data
recv from client: 5,awqr

> nc -v 127.0.0.1 3119
Connection to 127.0.0.1 3119 port [tcp/*] succeeded!
asdh
awqr


推荐阅读
author-avatar
曹月洪_867
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有