1. 使用poll或epoll创建echo服务器
1. 说明:
此篇博客主要记录一种客户端实现方式,和两种使用poll或者epoll分别创建echo服务器的方式,具体可看代码注释:
2. 相关代码:
2.1 echoClient.cpp
#include <iostream>
#include <cstdio>
#include <cstring>#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>#define ERR_EXIT(m) \do {\perror(m); \exit(EXIT_FAILURE); \} while(0)int main() {int sock;struct sockaddr_in svrAddr, localAddr;socklen_t addrlen = sizeof(sockaddr);sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock < 0)ERR_EXIT("socket");memset(&svrAddr, 0, sizeof(svrAddr));svrAddr.sin_family = AF_INET;svrAddr.sin_port = htons(8888);svrAddr.sin_addr.s_addr = inet_addr("127.0.0.1");if (connect(sock, (sockaddr *)&svrAddr, sizeof(svrAddr)) < 0)ERR_EXIT("connect");if (getsockname(sock, (sockaddr *)&localAddr, &addrlen) < 0)ERR_EXIT("getsockname");std::cout << "ip = " << inet_ntoa(localAddr.sin_addr)<< " port = " << ntohs(localAddr.sin_port) << std::endl;char sendBuf[1024] = {0};char recvBuf[1024] = {0};while (fgets(sendBuf, sizeof(sendBuf), stdin) != NULL){write(sock, sendBuf, strlen(sendBuf));read(sock, recvBuf, sizeof(recvBuf));fputs(recvBuf, stdout);memset(sendBuf, 0, sizeof(sendBuf));memset(recvBuf, 0, sizeof(recvBuf));}close(sock);return 0;
}
2.2 echoServer_poll.cpp
#include <iostream>
#include <vector>
#include <string>#include <cstdio>
#include <cstring>#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <unistd.h>#include <signal.h>
#include <poll.h>
#include <sys/socket.h>#define ERR_EXIT(m) \do {\perror(m); \exit(EXIT_FAILURE); \} while(0)using PollfdList = std::vector<pollfd>;int main()
{//忽略系统提示的一些错误信号/*signal(para1,para2)para1:信号类型para2:信号处理函数(可以自定义)讲解参考:https://blog.csdn.net/u013271656/article/details/114537411*/signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);//创建一个监听套接字(非阻塞套接字)int listenfd;listenfd = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if(listenfd < 0){ERR_EXIT("socket");}//设置地址struct sockaddr_in srvAddr;memset(&srvAddr,0,sizeof(srvAddr));//初始化srvAddr.sin_family = AF_INET;srvAddr.sin_port = htons(8888);srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);//设置地址的重复利用int on = 1;if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ERR_EXIT("setsockopt");}//绑定if(bind(listenfd, (sockaddr *)&srvAddr, sizeof(srvAddr)) < 0){ERR_EXIT("bind");}//监听if(listen(listenfd, SOMAXCONN) < 0){ERR_EXIT("listen");}//使用poll并关注pollin事件struct pollfd pfd;pfd.fd = listenfd;pfd.events = POLLIN;//储存poll的描述符PollfdList pollfds;pollfds.push_back(pfd);int nready;struct sockaddr_in peerAddr;socklen_t peerlen;int connfd;int idlefd;//空闲描述符//循环处理while (true) {//取事件nready = poll(pollfds.data(), pollfds.size(), -1);if(nready == -1){if(errno == EINTR){continue;}ERR_EXIT("poll");}else if(nready == 0){continue;}//如果有POLLIN事件if(pollfds[0].revents & POLLIN){//接受peerlen = sizeof(peerAddr);connfd = ::accept4(listenfd, (sockaddr *)&peerAddr, &peerlen, SOCK_NONBLOCK | SOCK_CLOEXEC);//剔除空闲连接if (connfd == -1) {if (errno == EMFILE) {close(idlefd);idlefd = accept(listenfd, NULL, NULL);close(idlefd);idlefd = open("/dev/null", O_RDONLY | O_CLOEXEC);continue;}else ERR_EXIT("accept4");}//加入到监听pfd.fd = connfd;pfd.events = POLL_IN;pfd.revents = 0;pollfds.push_back(pfd);--nready;//连接成功std::cout << "ip = " << inet_ntoa(peerAddr.sin_addr)<< " port = " << ntohs(peerAddr.sin_port) << std::endl;if (nready == 0)continue;}//std::cout << "pollfds size: " << pollfds.size() << std::endl;//std::cout << "nready fds: " << nready << std::endl;//遍历判断哪些套接字产生了事件for (auto it = pollfds.begin() + 1; it != pollfds.end() && nready > 0; ++it) {//如果是可读事件if (it->revents & POLL_IN) {--nready;connfd = it->fd;char buf[1024] = {0};//读取数据int ret = read(connfd, buf, 1024);if (ret == -1)ERR_EXIT("read");if (ret == 0) {std::cout << "client closed" << std::endl;it = pollfds.erase(it);--it;close(connfd);continue;}std::cout << buf << std::endl;//将接收的消息返回给客户端write(connfd, buf, strlen(buf));}}}return 0;
}
2.3 echoServer_epoll.cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>#include <cstdio>
#include <cstring>#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <unistd.h>#include <signal.h>
#include <sys/epoll.h>
#include <sys/socket.h>#define ERR_EXIT(m) \do {\perror(m); \exit(EXIT_FAILURE); \} while(0)using EventList = std::vector<epoll_event>;int main()
{signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);//创建一个监听套接字(非阻塞套接字)int listenfd;listenfd = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if(listenfd < 0){ERR_EXIT("socket");}//设置地址struct sockaddr_in srvAddr;memset(&srvAddr,0,sizeof(srvAddr));//初始化srvAddr.sin_family = AF_INET;srvAddr.sin_port = htons(8888);srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);//设置地址的重复利用int on = 1;if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0){ERR_EXIT("setsockopt");}//绑定if(bind(listenfd, (sockaddr *)&srvAddr, sizeof(srvAddr)) < 0){ERR_EXIT("bind");}//监听if(listen(listenfd, SOMAXCONN) < 0){ERR_EXIT("listen");}std::vector<int> clients;int epollfd = epoll_create(EPOLL_CLOEXEC);//使用EPOLLIN并关注EPOLLIN事件struct epoll_event event;event.data.fd = listenfd;event.events = EPOLLIN;epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &event);//储存epoll的描述符EventList events(16);struct sockaddr_in peerAddr;socklen_t peerlen;int connfd;int idlefd;//空闲描述符int nready;//循环处理while (true) {//取事件nready = epoll_wait(epollfd, events.data(), static_cast<int>(events.size()), -1);if(nready == -1){if(errno == EINTR){continue;}ERR_EXIT("epoll_wait");}else if(nready == 0){continue;}if (static_cast<size_t>(nready) == events.size()) {events.resize(events.size() * 2);} for (auto e : events) {if (e.data.fd == listenfd) {peerlen = sizeof(peerAddr);connfd = ::accept4(listenfd, (sockaddr *)&peerAddr, &peerlen, SOCK_NONBLOCK | SOCK_CLOEXEC);if (connfd == -1) {if (errno == EMFILE) {close(idlefd);idlefd = accept(listenfd, NULL, NULL);close(idlefd);idlefd = open("/dev/null", O_RDONLY | O_CLOEXEC);continue;}else ERR_EXIT("accept4");}clients.push_back(connfd);event.data.fd = connfd;event.events = EPOLLIN;epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event);std::cout << " connection from ip = " << inet_ntoa(peerAddr.sin_addr)<< " port = " << ntohs(peerAddr.sin_port) << std::endl;}else if (e.events & EPOLLIN) {connfd = e.data.fd;char buf[1024] = {0};int ret = read(connfd, buf, 1024);if (ret == -1)ERR_EXIT("read");if (ret == 0) {std::cout << "client closed" << std::endl;event = e; epoll_ctl(epollfd, EPOLL_CTL_DEL, connfd, &event);clients.erase(std::remove(clients.begin(), clients.end(), connfd), clients.end());close(connfd);continue;}std::cout << "msg: " << buf << std::endl;write(connfd, buf, strlen(buf));}}}return 0;
}
相关文章:
1. 使用poll或epoll创建echo服务器
1. 说明: 此篇博客主要记录一种客户端实现方式,和两种使用poll或者epoll分别创建echo服务器的方式,具体可看代码注释: 2. 相关代码: 2.1 echoClient.cpp #include <iostream> #include <cstdio> #incl…...
【对象数组根据属性排序】
// sort使用的排序方法 // 传入对象数组用于排序的对象的属性,升序/降序 function compare(property, sortType "asc") {debugger// 如果不是 asc,desc,不做下一步比较if (!(sortType "desc" || sortType "asc")) {return;}return function (…...

BACnet I/O模块:楼宇自动化的未来选择
在楼宇自动化领域,BACnet通信协议在确保设备之间无缝高效的数据交换方面发挥着至关重要的作用。该领域使用广泛的协议是BACnet。它使传感器、执行器和控制器等设备能够相互通信,从而促进工业过程的自动化。 BACNET介绍 BACnet是专门为楼宇自动化和控制系…...

android项目实战之使用框架 集成多图片、视频的上传
效果图 实现方式,本功能使用PictureSelector 第三方库 。作者项目地址:https://github.com/LuckSiege/PictureSelector 1. builder.gradle 增加 implementation io.github.lucksiege:pictureselector:v3.11.1implementation com.tbruyelle.rxpermissio…...
MyBatis查询优化:枚举在条件构建中的妙用
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…...

Isaac Sim教程04 Isaac Sim的高级使用
Isaac Sim 高级使用 版权信息 Copyright 2023 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The author holds…...

《数据结构、算法与应用C++语言描述》-线索二叉树的定义与C++实现
_23Threaded BinaryTree 可编译运行代码见:GIithub::Data-Structures-Algorithms-and-Applications/_24Threaded_BinaryTree 线索二叉树定义 在普通二叉树中,有很多nullptr指针被浪费了,可以将其利用起来。 首先我们要来看看这空指针有多少…...

删除误提交的 git commit
背景描述 某次的意外 commit 中误将密码写到代码中并且 push 到了 remote repo 里面, 本文将围绕这个场景讨论如何弥补. 模拟误提交操作 在 Gitee 创建一个新的 Repo, clone 到本地 git clone https://gitee.com/lpwm/myrepo.git创建两个文件, commit 后 push 到 remote 作…...
机器学习---pySpark案例
1、统计PV,UV 1.if __name__ __main__: 2. conf SparkConf() 3. conf.setMaster("local") 4. conf.setAppName("test") 5. sc SparkContext(confconf) 6. 7. #pv 8. sc.textFile("./pvuv").map(lambda line:(l…...

【链表Linked List】力扣-24 两两交换链表中的节点
目录 题目描述 解题过程 题目描述 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入:he…...
企业微信协议开发,API接口调用
产品说明 一、 hook版本:企业微信hook接口是指将企业微信的功能封装成dll,并提供简易的接口给程序调用。通过hook技术,可以在不修改企业微信客户端源代码的情况下,实现对企业微信客户端的功能进行扩展和定制化。企业微信hook接口…...

代码随想录算法训练营 ---第五十五天
今天是 动态规划:编辑距离问题。 第一题: 简介: 动态规划五部曲: 1.确定dp数组的含义 dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]。 2.确定递推公…...

【Intel/Altera】 全系列FPGA最新汇总说明,持续更新中
前言 2023年11月14日英特尔 FPGA中国技术日,Intel刚发布了新的FPGA系列,官网信息太多,我这里结合以前的信息,简单汇总更新一下,方便大家快速了解Intel/Altera FPGA家族。 目录 前言 Altera和Intel 型号汇总 1. Agi…...
利用flask将yolov5算法封装成在线推理服务
本脚本主要参考了yolov5工程文件夹下面的detect.py,将yolov5算法封装成了一个在线的推理服务,可以接受app请求,然后推理图片,并将检测结果以json返回,该服务可以供数据标注平台请求。 from flask import * import shutil import json import os import pynvml import pand…...
vue3父子传值实现弹框功能
在Vue3中,我们可以通过 provide 和 inject 来实现父子组件之间的数据传递,这也适用于实现弹框功能。下面是一个简单的例子: 父组件代码: <template><div><button click"showDialog">打开弹框</b…...
C++入门【2-C++ 数据类型】
C 数据类型 使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。 您可能需要存储各种数据类型(比如字符型、宽字符型、整型…...
按照官网文档 通过useExtendedLib扩展库 引入WeUI,报错 组件未定义 | 解决办法
检查开发者工具版本是否过老 参考博客 不要使用 游客模式,游客模式不支持,请注册Appid 使用。 注意 扩展库方式 和 npm 方式不能同时使用,会有相应报错...

Chat-GPT原理
Chat-GPT原理核心:基于Transformer 架构 以下是参考文献的部分截图原文说明: Transformers are based on the “attention mechanism,” which allows the model to pay more attention to some inputs than others, regardless of where they show up in t…...

GODOC命令无效,原因是需要手动安装
在看《GO程序设计语言》这本书,按照其中的内容,想看下GO自带的包的文档。 书中讲,可以直接输入GoDOC命令来打开一个服务器,从而可以用浏览器访问文档库。输入命令后,系统提示找不到该命令。 查了资料后才发现ÿ…...

忽略python运行出现的大量警告
添加以下代码即可 import warnings warnings.filterwarnings(ignore)...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...