【计算机网络 - 基础问题】每日 3 题(五十五)

news/2024/10/27 16:50:47/

✍个人博客:https://blog.csdn.net/Newin2020?type=blog
📣专栏地址:http://t.csdnimg.cn/fYaBd
📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
📝推荐参考地址:https://www.xiaolincoding.com/(这个大佬的专栏非常有用!)

163. select API 介绍

主旨思想:
首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中。
调用一个系统函数,监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行 I/O 操作时,该函数才返回。

  • 这个函数是阻塞
  • 函数对文件描述符的检测的操作是由内核完成的

在返回时,它会告诉进程有多少(哪些)描述符要进行 I/O 操作。

// sizeof(fd_set) = 128     1024
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
/*- 参数:- nfds : 委托内核检测的最大文件描述符的值 + 1- readfds : 要检测的文件描述符的读的集合,委托内核检测哪些文件描述符的读的属性- 一般检测读操作- 对应的是对方发送过来的数据,因为读是被动的接收数据,检测的就是读缓冲- 是一个传入传出参数- writefds : 要检测的文件描述符的写的集合,委托内核检测哪些文件描述符的写的属性- 委托内核检测写缓冲区是不是还可以写数据(不满的就可以写)- exceptfds : 检测发生异常的文件描述符的集合- timeout : 设置的超时时间struct timeval {long    tv_sec;         / seconds /long    tv_usec;        / microseconds /};- NULL : 永久阻塞,直到检测到了文件描述符有变化- tv_sec = 0 tv_usec = 0, 不阻塞- tv_sec > 0 tv_usec > 0, 阻塞对应的时间- 返回值 : - -1 : 失败- >0(n) : 检测的集合中有n个文件描述符发生了变化
*/// 将参数文件描述符fd对应的标志位设置为0
void FD_CLR(int fd, fd_set *set);
// 判断fd对应的标志位是0还是1, 返回值 : fd对应的标志位的值,0,返回0, 1,返回1
int  FD_ISSET(int fd, fd_set *set);
// 将参数文件描述符fd 对应的标志位,设置为1
void FD_SET(int fd, fd_set *set);
// fd_set一共有1024 bit, 全部初始化为0
void FD_ZERO(fd_set *set);

164. select 分析

select() 工作过程分析

在这里插入图片描述

select() 多路复用

在这里插入图片描述

select() 的缺点

在这里插入图片描述

165. select 案例

select.c

#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>int main() {// 创建socketint lfd = socket(PF_INET, SOCK_STREAM, 0);struct sockaddr_in saddr;saddr.sin_port = htons(9999);saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = INADDR_ANY;// 绑定bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));// 监听listen(lfd, 8);// 创建一个fd_set的集合,存放的是需要检测的文件描述符fd_set rdset, tmp;FD_ZERO(&rdset);FD_SET(lfd, &rdset);int maxfd = lfd;while(1) {tmp = rdset;// 调用select系统函数,让内核帮检测哪些文件描述符有数据int ret = select(maxfd + 1, &tmp, NULL, NULL, NULL);if(ret == -1) {perror("select");exit(-1);} else if(ret == 0) {continue;} else if(ret > 0) {// 说明检测到了有文件描述符的对应的缓冲区的数据发生了改变if(FD_ISSET(lfd, &tmp)) {// 表示有新的客户端连接进来了struct sockaddr_in cliaddr;int len = sizeof(cliaddr);int cfd = accept(lfd, (struct sockaddr *)&cliaddr, &len);// 将新的文件描述符加入到集合中FD_SET(cfd, &rdset);// 更新最大的文件描述符maxfd = maxfd > cfd ? maxfd : cfd;}for(int i = lfd + 1; i <= maxfd; i++) {if(FD_ISSET(i, &tmp)) {// 说明这个文件描述符对应的客户端发来了数据char buf[1024] = {0};int len = read(i, buf, sizeof(buf));if(len == -1) {perror("read");exit(-1);} else if(len == 0) {printf("client closed...\n");close(i);FD_CLR(i, &rdset);} else if(len > 0) {printf("read buf = %s\n", buf);write(i, buf, strlen(buf) + 1);}}}}}close(lfd);return 0;
}

client.c

#include <stdio.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main() {// 创建socketint fd = socket(PF_INET, SOCK_STREAM, 0);if(fd == -1) {perror("socket");return -1;}struct sockaddr_in seraddr;inet_pton(AF_INET, "127.0.0.1", &seraddr.sin_addr.s_addr);seraddr.sin_family = AF_INET;seraddr.sin_port = htons(9999);// 连接服务器int ret = connect(fd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret == -1){perror("connect");return -1;}int num = 0;while(1) {char sendBuf[1024] = {0};sprintf(sendBuf, "send data %d", num++);write(fd, sendBuf, strlen(sendBuf) + 1);// 接收int len = read(fd, sendBuf, sizeof(sendBuf));if(len == -1) {perror("read");return -1;}else if(len > 0) {printf("read buf = %s\n", sendBuf);} else {printf("服务器已经断开连接...\n");break;}// sleep(1);usleep(1000);}close(fd);return 0;
}

http://www.ppmy.cn/news/1542378.html

相关文章

笔记整理—linux驱动开发部分(2)模块信息与编译

对于linux而言&#xff0c;.ko文件为驱动文件&#xff0c;在终端可以使用lsmod列出已经安装的模块&#xff0c;使用insmod xxx.ko安装所需要的模块&#xff0c;modinfo xxx.ko打印某个模块提供的信息&#xff0c;rmmod xxx卸载某个不需要的模块。 insmod与module_init宏。在源代…

PgSQL常用SQL语句

PgSQL常用SQL语句 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 PgSQL是一种开源的关系型数据库管理系统&#xff0c;它是PostgreSQL的一种实现。本文将介绍一些常用的PgSQL SQL语句&a…

Kafka 解决消息丢失、乱序与重复消费

一、引言 在分布式系统中&#xff0c;Apache Kafka 作为一种高吞吐量的分布式发布订阅消息系统&#xff0c;被广泛应用于日志收集、流式处理、消息队列等场景。然而&#xff0c;在实际使用过程中&#xff0c;可能会遇到消息丢失、乱序、重复消费等问题&#xff0c;这些问题可能…

深入解析 Jenkins 自动化任务链:三大方法实现任务间依赖与状态控制

文章目录 前言1. 使用 “Build Trigger”&#xff08;构建触发器&#xff09;2. 使用 Jenkins Pipeline 实现任务触发3. 使用 Jenkins 的 “Parameterized Trigger Plugin” 插件例子1&#xff1a;任务 A 成功后自动执行任务 B例子2&#xff1a;任务 A 成功后自动执行 Pipeline…

模板语法(1)

一、文本&#xff1a; 在html中通过{{}}&#xff08;双大括号&#xff09;中可以把Vue对象中的数据插入到网页中。并且只要Vue对象上对应的值发生改变了&#xff0c;那么html中双大括号中的值也会立马改变。 <script setup name"App">import { ref } from vu…

【ArcGIS Pro实操第4期】绘制三维地图

【ArcGIS Pro实操第4期】绘制三维地图 ArcGIS Pro绘制三维地图-以DEM高程为例参考 如何使用ArcGIS Pro将栅格数据用三维的形式进行表达&#xff1f;在ArcGIS里可以使用ArcScene来实现&#xff0c;ArcGIS Pro实现原理跟ArcScene一致。由于Esri未来将不再对ArcGIS更新&#xff0c…

基于SpringBoot的酒店管理系统的设计与实现

摘要 酒店管理系统的设计旨在提供快捷高效的住宿资源管理方案&#xff0c;帮助管理员实现对酒店内房间、客户信息、订单的全方位管理&#xff0c;同时为用户提供便捷的预订和查询功能。本系统基于Spring Boot框架&#xff0c;结合前端框架和数据库设计&#xff0c;构建一个用户…

Linux TCP CC状态机

万字详文&#xff1a;TCP 拥塞控制详解 - 知乎bcc/tools/tcpcong.py at master iovisor/bccbcc/tools/tcpcong_example.txt at master iovisor/bcc 1.状态机 2.tcp map