热门标签 | 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


推荐阅读
  • 本文介绍如何使用线段树解决洛谷 P1531 我讨厌它问题,重点在于单点更新和区间查询最大值。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 本文提出了一种基于栈结构的高效四则运算表达式求值方法。该方法能够处理包含加、减、乘、除运算符以及十进制整数和小括号的算术表达式。通过定义和实现栈的基本操作,如入栈、出栈和判空等,算法能够准确地解析并计算输入的表达式,最终输出其计算结果。此方法不仅提高了计算效率,还增强了对复杂表达式的处理能力。 ... [详细]
  • 深入解析C语言中结构体的内存对齐机制及其优化方法
    为了提高CPU访问效率,C语言中的结构体成员在内存中遵循特定的对齐规则。本文详细解析了这些对齐机制,并探讨了如何通过合理的布局和编译器选项来优化结构体的内存使用,从而提升程序性能。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • importpymysql#一、直接连接mysql数据库'''coonpymysql.connect(host'192.168.*.*',u ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 本文详细介绍了如何使用Python中的smtplib库来发送带有附件的邮件,并提供了完整的代码示例。作者:多测师_王sir,时间:2020年5月20日 17:24,微信:15367499889,公司:上海多测师信息有限公司。 ... [详细]
  • 你的问题在于:1. 代码格式混乱,缺乏必要的缩进,导致可读性极低;2. 使用 `strlen()` 和 `malloc()` 函数时,必须包含相应的头文件;3. `write()` 函数的返回值处理不当,建议检查并处理其返回值以确保程序的健壮性。此外,建议在编写代码时遵循良好的编程规范,增加代码的可维护性和可读性。 ... [详细]
  • ### 优化后的摘要本文对 HDU ACM 1073 题目进行了详细解析,该题属于基础字符串处理范畴。通过分析题目要求,我们可以发现这是一道较为简单的题目。代码实现中使用了 C++ 语言,并定义了一个常量 `N` 用于字符串长度的限制。主要操作包括字符串的输入、处理和输出,具体步骤涉及字符数组的初始化和字符串的逆序操作。通过对该题目的深入探讨,读者可以更好地理解字符串处理的基本方法和技巧。 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 在深入探讨进程间通信技术时,本文重点解析了描述符传递的方法。通过详细分析发送和接收描述符的过程,文章首先介绍了发送描述符的具体步骤,并提供了相关函数原型。此外,还讨论了如何高效地在不同进程之间传输文件描述符,以实现资源的共享和同步。这一技术在多进程应用中具有重要意义,能够显著提升系统的性能和可靠性。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
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社区 版权所有