Linux IO模型:IO多路复用
● 应用程序中同时处理多路输入输出流,若采用阻塞模式,得不到预期的目的;
● 若采用非阻塞模式,对多个输入进行轮询,但又太浪费CPU时间;
● 若设置多个进程/线程,分别处理一条数据通路,将新产生进程/线程间的同步与通信问题,使程序变得更加复杂;
● 比较好的方法是使用I/O多路复用技术。
其(select)基本思想是:
○ 先构造一张有关描述符的表(最大1024),然后调用一个函数。
○ 当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。
○ 函数返回时告诉进程哪个描述符已就绪,可以进行I/O操作。
用select创建并发服务器,可以与多个客户端进行通信(监听键盘、socket、多个acceptfd)
循环服务器:一个客户端可以连接多个客户端,但是不能同时
并发服务器:一个服务器可以同时处理多个客户端的请求
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>// tcp服务器一共有两种文件描述符,一类用于连接,一类用于通信
int main(int argc, char const *argv[])
{char buf[128];int ret;if (argc != 2){printf("usage:%s <端口号>\n", argv[0]);return -1;}// 1.创建套接字(socket)// socket函数返回值:用于连接的文件描述符int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err");return -1;}printf("sockfd:%d\n", sockfd);// 2. 指定网络信息struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET; // IPV4saddr.sin_port = htons(atoi(argv[1])); // 端口号// saddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // 虚拟机IP地址(自动获取)saddr.sin_addr.s_addr = INADDR_ANY; // 虚拟机IP地址// INADDR_ANY是一个常量,它指代的是一个特殊的IP地址,即0.0.0.0// 在网络编程中,当一个进程需要绑定一个网络端口时,可以使用INADDR_ANY来指定该端口可以接受来自任何IP地址的连接请求int len = sizeof(caddr);// 3.绑定套接字(bind)if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind err");return -1;}printf("bind ok\n");// 4.监听套接字(listen)if (listen(sockfd, 6) < 0){perror("listen err");return -1;}printf("listen ok\n");//******************************************************************//// 1)构造一张关于文件描述符的表fd_set rfds, tempfds;int maxfd;// 2)清空表 FD_ZEROFD_ZERO(&rfds);FD_ZERO(&tempfds);// 3)将关心的文件描述符添加到表中 FD_SETFD_SET(sockfd, &rfds);FD_SET(0, &rfds);maxfd = sockfd;while (1){// 将原来的表复制给新表tempfds = rfds;struct timeval tm = {1, 0}; // 超时检测// 4)调用select函数,监听 selectret = select(maxfd + 1, &tempfds, NULL, NULL, 0);if (ret < 0){perror("select err");return -1;}else if(ret==0){printf("time out\n");}// 5)判断到底是哪一个或者是哪些文件描述符发生了事件 FD_ISSETif (FD_ISSET(0, &tempfds)){fgets(buf, sizeof(buf), stdin);printf("keybroad:%s\n", buf);}if (FD_ISSET(sockfd, &tempfds)){// 5.接受客户端连接请求(accept)// accept函数返回值:用于通信的文件描述符int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);if (acceptfd < 0){perror("accpet err");return -1;}printf("port:%d ip:%s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));printf("accpetfd:%d\n", acceptfd);// 将用于通信的文件描述符加入表中FD_SET(acceptfd, &rfds);if (acceptfd > maxfd)maxfd = acceptfd;}for (int i = sockfd + 1; i <= maxfd; i++) // 循环判断哪些文件描述符发生响应{if (FD_ISSET(i, &tempfds)){// 6. 接收,发送数据(recv,send)ret = recv(i, buf, sizeof(buf), 0);if (ret < 0){perror("recv err");break;}else if (ret == 0){printf("client %d exit\n", i);close(i); // 关闭退出的客户端文件描述符FD_CLR(i, &rfds); // 将关闭的文件描述符从表中删除while (!FD_ISSET(maxfd, &rfds))maxfd--;}else{printf("client %d: %s\n", i, buf);memset(buf, 0, sizeof(buf));}}}}//*****************************************************************//// 7.关闭套接字(close)close(sockfd);return 0;
}
使用poll实现client的收发功能
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <poll.h>
int main(int argc, char const *argv[])
{char buf[128];if (argc != 3){printf("usage:%s <IP地址> <端口号>\n", argv[0]);return -1;}// 1.创建套接字(socket)int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err");return -1;}printf("sockfd:%d\n", sockfd);// 2.指定(服务器)网络信息struct sockaddr_in saddr;saddr.sin_family = AF_INET; // IPV4saddr.sin_port = htons(atoi(argv[2])); // 端口号saddr.sin_addr.s_addr = inet_addr(argv[1]); // 虚拟机IP地址// 3.连接(connect)if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("connect err");return -1;}printf("connect ok\n");// 4.接收发送消息(recv send)//************************************************************//// 1)创建结构体数组struct pollfd fds[2];// 2)将关心的文件描述符添加到数组中,并赋予事件fds[0].fd = 0; // 键盘fds[0].events = POLLIN; // 想要发生的事件fds[1].fd = sockfd; // 套接字fds[1].events = POLLIN; // 想要发生的事件// 3)保存数组内最后一个有效元素的下标int last = 1;// 4)调用poll函数,监听while (1){int ret = poll(fds, last + 1, 0);if (ret < 0){perror("poll err");return -1;}// 5)判断结构体内文件描述符实际触发的事件if (fds[0].revents == POLLIN){// 6)根据不同文件描述符触发的不同事件做对应的逻辑处理fgets(buf, sizeof(buf), stdin);// printf("keybroad:%s\n", buf);send(sockfd, buf, sizeof(buf), 0);if (strcmp(buf, "quit\n") == 0)break;}if (fds[1].revents == POLLIN){recv(sockfd, buf, sizeof(buf), 0);printf("buf:%s\n", buf);}memset(buf, 0, sizeof(buf));}//************************************************************//// 5.关闭套接字(close)close(sockfd);return 0;
}
相关文章:
Linux IO模型:IO多路复用
● 应用程序中同时处理多路输入输出流,若采用阻塞模式,得不到预期的目的; ● 若采用非阻塞模式,对多个输入进行轮询,但又太浪费CPU时间; ● 若设置多个进程/线程,分别处理一条数据通路ÿ…...
[数据集][目标检测]电梯内广告牌电动车检测数据集VOC+YOLO格式2787张4类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2787 标注数量(xml文件个数):2787 标注数量(txt文件个数):2787 标注…...
MATLAB下载详细教程及下载链接
欢迎大家进评论区交流经验 1. 准备工作 下载MATLAB安装包:首先,从MathWorks官方网站(http://www.mathworks.com)下载适合您操作系统的MATLAB安装包。确保选择与您的操作系统(如Windows、macOS或Linux)兼容的…...
利用发电量和气象数据分析来判断光伏仿真系统的准确性
随着光伏产业的迅速发展,光伏仿真系统通过集成气象数据分析、发电量分析、投融资分析及损耗估算等功能,为光伏项目的全生命周期管理提供了科学依据。 光伏仿真系统集成了气象数据分析、发电量预测、投融资分析、损耗估算及光伏设计等功能。其中…...
Model-based RL动态规划(基于价值、基于策略,泛化迭代)
白盒环境和黑盒环境 白盒环境:知道环境的状态转移函数P(s’|s)或P(s’|s,a)和奖励函数R(s)或R(s,a): 白盒环境下的学习相当于直接给出了有监督学习的数据分布(就是有了目标靶子),不需要采样了,直接最小…...
外接串口板,通过串口打开adb模式
一、依赖库 import subprocess import serial from serial.tools import list_ports import logging import time 二、代码 import subprocessimport serial from serial.tools import list_ports import logging import timedef openAdb(com):# com []# for i in list_por…...
ssm微信小程序校园失物招领论文源码调试讲解
第二章 开发技术与环境配置 以Java语言为开发工具,利用了当前先进的SSM框架,以MyEclipse10为系统开发工具,MySQL为后台数据库,开发的一个微信小程序校园失物招领。 2.1 Java语言简介 Java是由SUN公司推出,该公司于20…...
iOS 15推出后利用邮件打开率的7种方法
自从苹果在2021年底推出iOS 15以来,邮件打开率就一直是一个让人头疼的指标。 Klaviyo市场情报主管Mindy Regnell表示:“对于启用了Apple邮件隐私保护(MPP)的用户来说,苹果会打开这些邮件并预先下载内容到他们的服务器…...
以太网--TCP/IP协议(一)
概述 以太网是局域网的一种,其他的比如还有令牌环、FDDI。和局域网对应的就是广域网,如Internet,城域网等。 从网络层次看,局域网协议主要偏重于低层(业内一般把物理层、数据链路层归为低层)。以太网协议…...
LeetCode刷题:找到第K大的元素
本题其实就是考察排序算法,为了减低时间复杂度,所以采用堆排序 import java.security.Key; import java.util.Scanner;public class FindKtopElements {public static void main(String[] args) {Scanner scanner new Scanner(System.in);String lin…...
HTML页面配置高德地图,获取位置
HTML页面配置高德地图,获取位置 一、使用情况 1、之前项目用的前后端分离框架,所以用Vue接入的高德地图,自动搜索补全,是请求的后台返回的数据。 2、现在用单体项目,前端是Bootstrap,需要接高德地图&…...
HTTrack
--不破不立 HTTrack 是一个免费开源的网站离线浏览器。通过它可以将整个网站下载到本地的某个目录,包括 html、图片和脚本以及样式文件,并对其中的链接进行重构以便于在本地进行浏览。 1.官网下载地址:https://www.httrack.com/page/2/en/in…...
干货分享|分享一款微软出品的工作效率神器 PowerToys
工具介绍:Microsoft PowerToys 是一组实用工具,可帮助高级用户调整和简化其 Windows 体验,从而提高工作效率。 安装步骤:直接打开微软商店安装即可,并且可以保证下载到最新版本。 功能介绍: 高级粘贴 高级…...
神经网络的线性部分和非线性部分
神经网络的线性部分和非线性部分是其构成中的两个核心元素,它们共同决定了模型的能力和行为。让我们分别看一下这两部分: 1. 线性部分 线性部分通常是指神经网络中的加权和操作。这部分可以用以下形式表示: [ z W \cdot x b ] W 是权重…...
微信支付开发避坑指南
1 微信支付的坑 1.1 不能用前端传递过来的金额 订单的商品金额要从数据库获取,前端只传商品 id。 1.2 交易类型trade type字段不要传错 v2版API,不同交易类型,要调用的支付方式也不同。 1.3 二次签名 下单时,在拿到预支付交…...
Qt5.4.1连接odbc驱动操作达梦数据库
Qt5.4.1连接odbc驱动操作达梦数据库 1 环境介绍2 Qt5.4.1 安装2.1 图形化界面安装Qt5.4.12.2 配置Qt5.4.1 环境变量2.3 Qt5.4.1 生成 libqsqlodbc.so 并配置2.3.1 生成Makefile2.3.2 查看 libqsqlodbc.so 文件并配置 3 配置Qt测试用例4 达梦数据库学习使用列表 1 环境介绍 CPU…...
计算机组成原理(第一课)
计算机系统概述 1.发展史 摩尔定律:集成电路上可以容纳的晶体管数目在大约每经过18个月到24个月便会增加一倍 2.操作系统组成 存储程序程序控制 五个部分记住: 输入输出功能 I/O 记忆功能 访问 计算功能 计算 判断功能 判断 自我控制功能 自我控制…...
计算机网络练级第一级————认识网络
目录 网络搁哪? 网络的发展史(了解) 独立模式: 网络互联: 局域网时期: 广域网时期: 什么是协议 TCP/IP五层/四层模型 用官话来说: 我自己的话来说 第一层应用层࿱…...
Java基于微信小程序的家庭财务管理系统,附源码
博主介绍:✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不…...
P2343 宝石管理系统
不会写平衡树怎么办,可以用STL的vector或者是pb_ds,这个东西太乱,还是STL好用 #include<bits/stdc.h> using namespace std; int read() {int x 0, f 1;char ch getchar();while (ch < 0 || ch > 9) {if (ch -) f -1;ch g…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
