《TCP/IP网络编程》(第十三章)多种I/O函数(2)
使用
readv
和writev
函数可以提高数据通信的效率,它们的功能可以概括为**“对数据进行整合传输及发送”**。
即使用writev
函数可以将分散在多个缓冲中的数据一并发送,使用readv
函数可以由多个缓冲分别接受,所以适当使用他们可以减少I/O函数的调用次数。
1.readv
和writev
函数
①readv()
函数
用于从文件描述符中读取数据,并存储在多个缓冲区中。
ssize_t readv(
int fd, //文件描述符。
const struct iovec *iov, //指向 iovec 结构体数组的指针,iovec 结构体定义了一个缓冲区。
int iovcnt//iovec 结构体数组的元素个数。
);//iovec 结构体
struct iovec {void *iov_base; //指向缓冲区的起始地址(基地址)size_t iov_len; //缓冲区的长度,即需要传输的字节数
};
示例代码
#include<stdio.h>
#include<sys/uio.h>
#define BUF_SIZE 100
int main(int argc, char *argv[])
{struct iovec vec[2];char buf1[BUF_SIZE] = {0, };char buf2[BUF_SIZE] = {0, };int str_len;//设置两个缓存区,第一个存储5个字节,剩下的给第二个缓冲区vec[0].iov_base = buf1;vec[0].iov_len = 5;vec[1].iov_base = buf2;vec[1].iov_len = BUF_SIZE;str_len = readv(0, vec, 2);//第一个参数是0,即接受键盘输入printf("Read total bytes: %d \n", str_len);printf("First message: %s \n", buf1);printf("Second message: %s \n", buf2);return 0;
}
②writev()
函数
用于将多个缓冲区中的数据写入文件描述符,这种方法称为“聚集写”或“向量写”。
ssize_t writev(
int fd, //文件描述符
const struct iovec *iov, //指向 iovec 结构体数组的指针,iovec 结构体定义了一个缓冲区。
int iovcnt//iovec 结构体数组的元素个数。
);//iovec 结构体
struct iovec {void *iov_base; //指向缓冲区的起始地址(基地址)size_t iov_len; //缓冲区的长度,即需要传输的字节数
};
示例代码
#include<stdio.h>
#include<sys/uio.h>int main(int argc, char *argv[]){struct iovec vec[2];//有两个缓冲char buf1[] = "1234567890";char buf2[] = "ABCDEFGHIJ";int str_len;vec[0].iov_base = buf1;vec[0].iov_len = 10;vec[1].iov_base = buf2;vec[1].iov_len = 10;str_len = writev(1, vec, 2);//第一个参数是1,所以是向控制台输出puts("");printf("writev bytes: %d \n", str_len);
}
2.在Windows中实现紧急消息机制
在《TCP/IP网络编程》(第十三章)多种I/O函数(1)中已经基于Linux平台实现了MSG_OOB机制,但是是基于Linux的信号处理机制,所以无法直接移植到Windows平台。
若要在Windows平台上实现该机制,则需要通过select()
函数,该函数简介参考《TCP/IP网络编程》(第十二章)I/O复用(1)
PS:MSG_OOB在select()监视下会被视为异常数据
发送端代码
#include<stdio.h>
#include<stdlib.h>
#include<winsock2.h>#define BUFSIZE 30
void ErrorHandling(char* message);int main(int argc, char* argv[]){WSADATA wsa;SOCKET hSocket;SOCKADDR_IN sendAddr;if(argc!=3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2,2), &wsa) != 0){ErrorHandling("WSAStartup() error!");}hSocket = socket(PF_INET, SOCK_STREAM, 0);memset(&sendAddr, 0, sizeof(sendAddr));sendAddr.sin_family = AF_INET;sendAddr.sin_addr.s_addr = inet_addr(argv[1]);sendAddr.sin_port = htons(atoi(argv[2]));if(connect(hSocket, (SOCKADDR*)&sendAddr, sizeof(sendAddr)) == SOCKET_ERROR)ErrorHandling("connect() error!");send(hSocket, "123", 3, 0);send(hSocket, "4", 1, MSG_OOB);//带外数据在select的监视中,会被视为异常数据send(hSocket, "567", 3, 0);send(hSocket, "890", 3, MSG_OOB);//只把最后一个字节0作为紧急信息发送closesocket(hSocket);WSACleanup();return 0;
}void ErrorHandling(char* message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}
接受端代码
#include<stdio.h>
#include<stdlib.h>
#include<winsock2.h>#define BUFSIZE 30
void ErrorHandling(char *);int main(int argc, char *argv[]){WSADATA wsa;SOCKET hAcptSock, hRecvSock;SOCKADDR_IN sendAdr, recvAdr;int sendAdrSz,strLen;char buf[BUFSIZE];int result;fd_set read,except,read_copy,except_copy;struct timeval timeout;if(argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)ErrorHandling("WSAStartup() error!");hAcptSock = socket(PF_INET, SOCK_STREAM, 0);if(hAcptSock == INVALID_SOCKET)ErrorHandling("socket() error");memset(&recvAdr, 0, sizeof(recvAdr));recvAdr.sin_family = AF_INET;recvAdr.sin_addr.s_addr = htonl(INADDR_ANY);recvAdr.sin_port = htons(atoi(argv[1]));if(bind(hAcptSock, (SOCKADDR*)&recvAdr, sizeof(recvAdr)) == SOCKET_ERROR)ErrorHandling("bind() error");if(listen(hAcptSock, 5) == SOCKET_ERROR)ErrorHandling("listen() error");sendAdrSz = sizeof(sendAdr);hRecvSock = accept(hAcptSock, (SOCKADDR*)&sendAdr, &sendAdrSz);FD_ZERO(&read); // 清空reads集合FD_ZERO(&except); // 清空except集合FD_SET(hRecvSock, &read); // 将套接字添加到reads集合FD_SET(hRecvSock, &except); // 将套接字添加到except集合while(1){read_copy = read;except_copy = except;timeout.tv_sec = 5;timeout.tv_usec = 0;result = select(0, &read_copy, 0, &except_copy, &timeout);//开始监视文件描可读数集和与异常集合if(result>0){if(FD_ISSET(hRecvSock, &except_copy)){//使用FD_ISSET宏检查套接字是否在异常集合中。//如果是,表示发生了异常事件,此时会调用recv函数并指定MSG_OOB标志来接收带外数据strLen = recv(hRecvSock, buf, BUFSIZE-1, MSG_OOB);buf[strLen] = 0;printf("urgent message: %s \n", buf);}if(FD_ISSET(hRecvSock, &read_copy)){// 如果检测到读事件strLen = recv(hRecvSock, buf, BUFSIZE-1, 0);if(strLen == 0){break;closesocket(hRecvSock);}else{buf[strLen] = 0;printf("normal message: %s", buf);}}}}closesocket(hAcptSock);closesocket(hRecvSock);WSACleanup();return 0;
}void ErrorHandling(char *message){fputs(message, stderr);fputc('\n', stderr);exit(1);
}
优先接受MSG_OOB信息4和0。
相关文章:

《TCP/IP网络编程》(第十三章)多种I/O函数(2)
使用readv和writev函数可以提高数据通信的效率,它们的功能可以概括为**“对数据进行整合传输及发送”**。 即使用writev函数可以将分散在多个缓冲中的数据一并发送,使用readv函数可以由多个缓冲分别接受,所以适当使用他们可以减少I/O函数的调…...

Java集合汇总
Java中的集合框架是Java语言的核心部分,提供了强大的数据结构来存储和操作对象集合。集合框架位于java.util包中,主要可以分为两大类:Collection(单列集合)和Map(双列集合)。下面是对它们的总结…...

度小满金融大模型的应用创新
XuanYuan/README.md at main Duxiaoman-DI/XuanYuan GitHub...

Android WebView上传文件/自定义弹窗技术,附件的解决方案
安卓内核开发 其实是Android的webview默认是不支持<input type"file"/>文件上传的。现在的前端页面需要处理的是: 权限 文件路径AndroidManifest.xml <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/&g…...
selenium 输入框、按钮,输入点击,获取元素属性等简单例子
元素操作 nput框 输入send_keys, input框 清除clear(), 按钮 点击click() 按钮 提交submit() 获取元素 tag_name、 class属性值、 坐标尺寸 """ input框 输入1次,再追加输入一次, 清除, 再重新输入&…...
结构体构造函数
【知识点:结构体构造函数】下面两段代码等价。 (1)结构体构造函数写法 struct LinkNode {int data;LinkNode* next;LinkNode(int x):data(x),next(NULL) {} }; LinkNode* Lnew LinkNode(123); (2)非结构体构造函数写…...
基于单片机的电子万年历设计
摘要: 本设计以 AT89C51 单片机为主控器,使用 DS1302 时钟芯片、DS18B20 温度芯片、LCD1602 显示模块,利用Proteus 仿真软件和 Keil 编译软件进行了基于单片机的电子万年历仿真,设计的万年历可以在液晶上显示时间,同时还具有时间校准、温度显示等功能。 关键词 :单片机…...

大厂真实面试题(一)
滴滴大数据sql 取出累计值与1000差值最小的记录 1.题目 已知有表t_cost_detail包含id和money两列,id为自增,请累加计算money值,并求出累加值与1000差值最小的记录。 2.分析 本题主要是想找到累加值域1000差距最小的记录,也就是我们要对上述按照id进行排序并且累加,并…...

Docker搭建ELKF日志分析系统
Docker搭建ELKF日志分析系统 文章目录 Docker搭建ELKF日志分析系统资源列表基础环境一、系统环境准备1.1、创建所需的映射目录1.2、修改系统参数1.3、单击创建elk-kgc网络桥接 二、基于Dockerfile构建Elasticsearch镜像2.1、创建Elasticsearch工作目录2.2、上传资源到指定工作路…...

把系统引导做到U盘,实现插上U盘才能开机
前言 有个小伙伴提出了这样一个问题:能不能把U盘制作成电脑开机的钥匙? 小白稍微思考了一下,便做了这样一个回复:可以。 至于为什么要思考一下,这样会显得我有认真思考他提出的问题。 Windows7或以上系统均支持UEF…...

【计算机网络基础知识】
首先举一个生活化的例子,当你和朋友打电话时,你可能会使用三次握手和四次挥手的过程进行类比: 三次握手(Three-Way Handshake): 你打电话给朋友:你首先拨打你朋友的电话号码并等待他接听。这就…...

个股场外期权个人如何参与买卖?
个股场外期权作为一种金融衍生品,为个人投资者提供了多样化的投资选择和风险管理工具。想要参与个股场外期权的买卖,以下是一些关键步骤和考虑因素。 文章来源/:财智财经 第一步:选择合适的金融机构 首先,个人投资者需…...

程序猿大战Python——pycharm软件的使用
基础配置 目标:了解PyCharm软件的基础配置处理。 修改背景颜色: Appearance -> Theme 修改字体大小: 搜索font -> Font 例如,一起完成背景、字体大小的修改。 总结: (1)如果要对PyChar…...

Unity Standard shader 修改(增加本地坐标裁剪)
本想随便找一个裁剪的shader,可无奈的是没找到一个shader符合要求,美术制作的场景都是用的都标准的着色器他们不在乎你的功能逻辑需求,他们只关心场景的表现,那又找不到和unity标准着色器表现一样的shader 1.通过贴图的透明通道做…...

【数据结构】排序——插入排序,选择排序
前言 本篇博客我们正式开启数据结构中的排序,说到排序,我们能联想到我之前在C语言博客中的冒泡排序,它是排序中的一种,但实现效率太慢,这篇博客我们介绍两种新排序,并好好深入理解排序 💓 个人主…...
2024.6.9刷题记录
目录 一、1103. 分糖果 II 1.模拟 2.数学 二、312. 戳气球 1.递归-记忆化搜索 2.区间dp 三、2. 两数相加 1.迭代 2.递归-新建节点 3.递归-原节点 四、4. 寻找两个正序数组的中位数 1.堆 2.双指针二分 五、5. 最长回文子串 1.动态规划 2.中心扩展算法 六、6. Z…...

Matlab|遗传粒子群-混沌粒子群-基本粒子群
目录 1 主要内容 2 部分代码 3 效果图 4 下载链接 1 主要内容 很多同学在发文章时候最犯愁的就是创新点创新点创新点(重要的事情说三遍),对于采用智能算法的模型,可以采用算法改进的方式来达到提高整个文章创新水平的目的&…...

31|HTTP3:甩掉TCP、TLS 的包袱,构建高效网络
前面两篇文章我们分析了HTTP/1和HTTP/2,在HTTP/2出现之前,开发者需要采取很多变通的方式来解决HTTP/1所存在的问题,不过HTTP/2在2018年就开始得到了大规模的应用,HTTP/1中存在的一大堆缺陷都得到了解决。 HTTP/2的一个核心特性是…...

2 程序的灵魂—算法-2.2 简单算法举例-【例 2.3】
【例 2.3】判定 2000 — 2500 年中的每一年是否闰年,将结果输出。 润年的条件: 1. 能被 4 整除,但不能被 100 整除的年份; 2. 能被 100 整除,又能被 400 整除的年份; 设 y 为被检测的年份,则算法可表示如下…...
Python中的上下文管理器(contextlib)模块
Python中的contextlib模块提供了一些用于创建和管理上下文管理器(context managers)的工具。上下文管理器是实现了__enter__()和__exit__()方法的对象,它们通常用于确保在代码块执行前后执行某些操作,比如资源获取与释放、设置和重…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...