2024/03/19(网络编程·day5)
一、思维导图
二、selec函数实现TCP并发服务器
#include<myhead.h>#define SER_PORT 8888 //服务器端口号
#define SER_IP "192.168.117.116" //服务器IP
int main(int argc, const char *argv[])
{//1、创建一个套接字int sfd = -1;sfd = socket(AF_INET,SOCK_STREAM,0);//参数1:表示创建的是网络通信的套接字//参数2:表示使用的是TCP通信协议//参数3:参数2指定了协议,参数3填0即可if(sfd == -1){perror("socket error");return -1;}printf("%d success sfd = %d\n",__LINE__,sfd); //3//设置端口号快速重用int reuse = 1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、绑定IP和端口号//2.1填充地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET; //地址族sin.sin_port = htons(SER_PORT); //端口号sin.sin_addr.s_addr = inet_addr(SER_IP); //IP地址//2.2绑定if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))==-1){perror("bind error");return -1;}printf("%d bind success\n",__LINE__);//3、将套接字设置成被监听状态if(listen(sfd,128) == -1){perror("listen error");return -1;}//4、阻塞等待客户端的连接请求int newfd = -1;//定义结构体变量接受客户端地址信息结构体struct sockaddr_in cin;//接收客户端信息结构体socklen_t addrlen = sizeof(cin);//接收客户端结构体大小char sbuf[128] = ""; //服务器输入数据内容//11、定义一个文件描述符集合fd_set readfds,tempfds;//22、将集合清空FD_ZERO(&readfds);//33、将要被检测的文件描述符放入集合FD_SET(0,&readfds);FD_SET(sfd,&readfds);int maxfd = sfd; //记录当前容器中的最大文件描述符struct sockaddr_in cin_arr[1024]; //存储客户端信息结构体while(1){//将readfds备份tempfds = readfds;int res = select(maxfd+1,&tempfds,NULL,NULL,NULL); //阻塞等待集合中的事件产生if(res == -1){perror("select error");return -1;}else if(res == 0){printf("time out\n");return -1;}//当程序执行到此处说明集合中有事件产生,此时集合中只剩下本次触发事件的描述符for(int i=0;i<=maxfd;i++){//如果不是触发事件的文件描述符,直接跳过if(!FD_ISSET(i,&tempfds)){continue;}//程序执行至此,表示当前i文件描述符触发了事件//判断sfd是否触发事件if(i == sfd){if((newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen)) == -1){perror("accept error");return -1;}printf("[%s %d]:发来连接请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));//将客户端地址信息结构体放入容器中cin_arr[newfd] = cin;//将newfd放入readfds容器中参与检测FD_SET(newfd,&readfds);//可能要更新的maxfdif(newfd > maxfd){maxfd = newfd;}}//判断0号文件描述符是否触发事件else if(0 == i){fgets(sbuf,sizeof(sbuf),stdin); //终端输入sbuf[strlen(sbuf)-1] = 0;printf("触发了键盘输入事件:%s\n",sbuf);//将消息发送给所有客户端for(int i = 4;i<= maxfd;i++){send(i,sbuf,sizeof(sbuf),0);}printf("发送成功\n");}else{//说明某个客户端发来消息了,遍历所有客户端,判断是哪个发来的消息//5、收发数据char rbuf[128] = "";//接收客户端发送的信息//将容器清空bzero(rbuf,sizeof(rbuf));//memset(rbuf,0,sizeof(rbuf));//从套接字中读取数据int res = recv(i,rbuf,sizeof(rbuf)-1,0);if(res == 0){ printf("客户端已下线\n");//关闭与客户端通信的套接字close(i);//将当前文件描述符移除容器FD_CLR(i,&readfds);//可能要更新maxfdfor(int k=maxfd;k>=sfd;k--){if(FD_ISSET(k,&readfds)){maxfd = k;break;}}continue;}printf("[%s %d]:%s\n",inet_ntoa(cin_arr[i].sin_addr),ntohs(cin_arr[i].sin_port),rbuf);//加个收到再回回去strcat(rbuf," <Got it>!");send(i,rbuf,strlen(rbuf),0);printf("回复成功\n");}}}//6、关闭服务器close(sfd);return 0;
}
三、poll函数实现TCP客户端
#include<myhead.h>#define SER_PORT 8888 //服务器端口号
#define SER_IP "192.168.117.116" //服务器IP
#define CLI_PORT 9999 //客户端端口号
#define CLI_IP "192.168.117.116" //客户端IPint main(int argc, const char *argv[])
{//1、创建一个套接字int cfd = -1;cfd = socket(AF_INET,SOCK_STREAM,0);//参数1:表示创建的是网络通信的套接字//参数2:表示使用的是TCP通信协议//参数3:参数2指定了协议,参数3填0即可if(cfd == -1){perror("socket error");return -1;}printf("%d success cfd = %d\n",__LINE__,cfd); //3//设置端口号快速重用int reuse = 1;if(setsockopt(cfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、绑定IP和端口号//2.1填充客户端信息结构体struct sockaddr_in cin;cin.sin_family = AF_INET; //地址族cin.sin_port = htons(CLI_PORT); //端口号cin.sin_addr.s_addr = inet_addr(CLI_IP); //IP地址//2.2绑定if(bind(cfd,(struct sockaddr *)&cin,sizeof(cin))==-1){perror("bind error");return -1;}printf("bind success\n");//3、连接服务器//3.1、填充要连接服务器的地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET; //地质族sin.sin_port = htons(SER_PORT); //服务器端口号sin.sin_addr.s_addr = inet_addr(SER_IP); //服务器的IP地址//3.2、连接服务器if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin)) ==-1){perror("connect error");return -1;}printf("连接成功!\n");//使用poll完成0号文件描述符和cfd文件描述符的多路复用//11、准备文件描述符容器struct pollfd pfds[2];pfds[0].fd = 0; //文件描述符pfds[0].events = POLLIN; //检测读事件pfds[1].fd = cfd; //文件描述符pfds[1].events = POLLIN; //检测读事件//4、收发数据char wbuf[128] = "";while(1){int res = poll(pfds,2,-1); //阻塞检测集合中是否有事件发生if(res == -1){perror("poll error");return -1;}else if(res == 0){printf("time out\n");return -1;}//程序执行至此,说明检测的文件描述符集合中有事件发生//判断是否为0号文件描述符产生的事件if(pfds[0].revents == POLLIN){fgets(wbuf,sizeof(wbuf),stdin); //终端读取wbuf[strlen(wbuf)-1] = '\0'; //将换行换成'\0'//判断输入的字符串if(strcmp(wbuf,"quit") == 0){break;}//将数据发送给服务器send(cfd,wbuf,strlen(wbuf),0);}//判断是否为cfd文件描述符中产生了事件if(pfds[1].revents == POLLIN){//将字符数组清空bzero(wbuf,sizeof(wbuf));recv(cfd,wbuf,sizeof(wbuf)-1,0);printf("收到的服务器消息为:%s\n",wbuf);}}//5、关闭套接字close(cfd);return 0;
}
四、select函数实现的TCP并发服务器连接poll函数实现的TCP客户端
五、模拟面试
TCP通信中的三次握手和四次挥手过 程 | 三次握手: 2、服务器收到客户端的SYN请求后,会发送一个带有SYN和ACK标志的数据包作为应答,确认客户端的SYN,并选择自己的初始序列号,并对客户端的初始序列号进行确认。 3、客户端收到服务器的确认后,会发送一个带有ACK标志的数据包作为确认,表示连接建立成功。 四次挥手: 1、客户端已经发送完所有数据,想要关闭连接,于是发送一个带有FIN标志的数据包给服务器,表示不再发送数据。 2、服务器收到客户端的FIN后,会发送一个带有ACK标志的数据包作为确认,表示已收到关闭请求,但仍可以发送数据。 3、服务器发送完所有数据后,也想要关闭连接,于是发送一个带有FIN标志的数据包给客户端,表示不再发送数据。 4、客户端收到服务器的FIN后,会发送一个带有ACK标志的数据包作为确认,表示已收到关闭请求,连接终止。 |
并发和并行的区别 | 并发是指多个任务交替地快速执行,而并行是指多个任务同时执行。
|
阻寒IO和非阻塞IO的区别 | 阻塞 I/O 会导致程序在进行 I/O 操作时被挂起,而非阻塞 I/O 允许程序在等待 I/O 操作的同时继续执行其他任务。 在阻塞 I/O 中,当程序发起一个 I/O 操作时,程序会被阻塞,直到操作完成才能继续执行后续代码。 非阻塞 I/O 允许程序在发起一个 I/O 操作后立即返回,而不会等待操作完成。程序可以继续执行后续代码,然后再通过轮询或者事件通知等方式来检查 I/O 操作是否完成,如果完成则处理结果,否则继续进行其他任务。 |
同步和异步的区别 | 同步是顺序执行的,需要等待上一个操作完成才能执行下一个操作;而异步则是并发执行的,可以同时进行多个操作,不需要等待每个操作的完成。 在同步操作中,当一个操作被发起后,必须等待这个操作完成后才能继续执行后续的操作。 在异步操作中,当一个操作被发起后,不需要等待这个操作完成,可以继续执行后续的操作。 |
详细描述IO多路复用的原理 | ①将多个阻塞任务的文件描述符统一放入一个检测容器中。 ②用一个阻塞函数进行管理。 ③如果检测容器中有一个或者多个文件描述符对应的事件产生,就去解除阻塞,执行相应函数。 |
广播的相关内容 | 在IPv4网络中,广播地址通常是特定的IP地址,网络号+主机号全为1,表示向本地网络中的所有设备发送广播数据包。对发送端套接字设置为允许广播,发送端类似于UDP客户端,接收端类似于UDP服务器端。UDP广播的优点是简单直接,可以方便地向局域网中的所有设备发送消息。 |
组播的相关内容 | 组播地址是D类网络地址,需要对接收端设置加入多播组属性。 发送端类似于UDP的客户端,接收端类似于UDP的服务器端,实现的一对多的通信,不同于广播的是范围不同,只有加入多播组的主机才能通信了。 |
在使用套接字通信时,客户端就一定不需要绑 定操作吗 | 不一定,对于报式域套接字而言,如果客户端不绑定套接字文件,系统不会自动绑定,可以发送数据,但是服务器端不能向客户端发送消息。 |
目前学习的进程间通信方式有哪些 | 套接字,共享内存,有名管道,无名管道,信号,信号灯集,消息队列 |
线程的同步互斥机制 | 线程的同步互斥机制是指在多线程环境中控制线程之间执行顺序和共享资源访问,以确保线程之间的协调和正确性 同步互斥机制: 互斥锁(Mutex) 互斥锁是最常见的同步机制之一,用于保护临界区(一次只允许一个线程访问的资源或代码段),确保同一时间只有一个线程可以访问被锁定的资源。当一个线程获得了互斥锁后,其他线程需要等待直到该线程释放锁。 |
相关文章:

2024/03/19(网络编程·day5)
一、思维导图 二、selec函数实现TCP并发服务器 #include<myhead.h>#define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.117.116" //服务器IP int main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET,SOC…...
LeetCode解法汇总1969. 数组元素的最小非零乘积
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:. - 力扣(LeetCode) 描述: 给你一个正整数 p 。你有一个下标从 1 开…...

学习vue3第九节(新加指令 v-pre/v-once/v-memo/v-cloak )
1、v-pre 作用:防止编译器解析某个特定的元素及其内容,即v-pre 会跳过当前元素以及其子元素的vue语法解析,并将其保持原样输出; 用于:vue 中一些没有指令和插值表达式的节点的元素,使用 v-pre 可以提高 Vu…...

二开飞机机器人群发,实现自动给多个频道发送消息
频道1 频道2 二开代码部分: const CChatIdListprocess.env.CHANNEL_CHAT_ID_LIST; var channelChatIdArray CChatIdList.split(,);channelChatIdArray.forEach(function(item) {console.log(item); // 这里可以替换为您需要对数组中每个值进行的操作bot.sendM…...

AI如何支持慈善组织
为各种有意义的事业提供支持,无论是努力寻找治愈疾病的方法、研发使生活更轻松的技术,还是为有需要的人提供服务,都是无比崇高的使命。提供捐款或是投入时间支持的捐助者和志愿者往往对他们选择支持的事业的目标、服务和资源分配存有诸多疑虑…...

Git如何清除账户凭证
场景:一般发生在Git用户变更的情况 1.git base 操作 Git会使用凭证助手 credential.helper来储存账户凭证,通过以下命令移除: git config --system --unset credential.helper 除了system系统级外,还有 global、local范围。 查…...

【YUNBEE云贝-PostgreSQL】FDW应用
注: 本文为云贝教育 刘峰 原创,请尊重知识产权,转发请注明出处,不接受任何抄袭、演绎和未经注明出处的转载。 前言 Wrapper(FDW)是一项关键特性,它赋予数据库用户直接通过SQL语句访问存储于外部数据源的能…...

Spring MVC文件上传配置
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 文件上传 Spring MVC文件上传基于Servlet 3.0实现;示例代码如下: Overrideprotected void customizeRegistration(ServletRegistration.Dynamic reg…...

JavaScript高级(十八)---进程和线程,宏任务和微任务
进程和线程 进程(process):计算机已经运行的程序,是操作系统管理程序的一种方式,我们可以认为,启动一个应用程序,就会默认启动一个进程(也可能是多个进程)。 线程&…...
How to install mongodb on redhat 7.7
下载rpm: mongodb-enterprise-server-6.0.3-1.el7.x86_64.rpmmongodb-org-server-6.0.4-1.el7.x86_64.rpmmongodb-mms-6.0.9.100.20230201T2148Z.x86_64.rpm rpm -ivh mongodb-org-server-6.0.4-1.el7.x86_64.rpm rpm -ivh mongodb-mms-6.0.9.100.20230201T2148Z.x86_64.rpm …...

关于继承是怎么样的?那当然是很好理解之
本文描述了关于继承的大部分知识,但是并不全,每篇博客之间的知识都有互串,所以需要把几篇文章合起来看,学会融会贯通! 温馨提示:使用PC端观看,效果更佳! 目录 1.继承是什么 2.什…...

高可用系统有哪些设计原则
1.降级 主动降级:开关推送 被动降级:超时降级 异常降级 失败率 熔断保护 多级降级2.限流 nginx的limit模块 gateway redisLua 业务层限流 本地限流 gua 分布式限流 sentinel 3.弹性计算 弹性伸缩—K8Sdocker 主链路压力过大的时候可以将非主链路的机器给…...
LeetCode-回文数
LeetCode-回文数 解体思路: ①第一种:转换成字符串,使用字符串的现有api方法进行反转 ②第二种:直接使用循环除余乘10方法,进行反转 涉及知识点: 循环判断,StringBuffer,int类型…...

50. 【Linux教程】源码安装软件
本小节介绍如何使用软件的源码包安装软件,以安装 nginx 源码包为例。 1.下载软件源码包 使用如下命令下载 nginx 源码包: wget http://nginx.org/download/nginx-1.18.0.tar.gz执行结果如下图所示: 2.解压源码包 下载好了压缩包之后&#…...
《操作系统实践-基于Linux应用与内核编程》第10章--实验 Qt聊天程序
前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容,所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者:房胜、李旭健、黄…...

探究Kafka主题删除失败的根本原因
欢迎来到我的博客,代码的世界里,每一行都是一个故事 探究Kafka主题删除失败的根本原因 前言主题删除的基础主题删除的定义和作用:删除操作的基本流程: 可能存在删除异常的因素数据积压的处理方法Broker状态异常处理方法通用方法 前…...
JavaSE(上)-Day7
JavaSE(上)-Day7 类和对象封装privatethis构造方法标准JavaBean对象的内存图执行Test类main方法生成一个User对象的内存过程 基本数据类型和引用数据类型的区别this的内存原理成员变量和局部变量区别 类和对象 类是设计图纸,对象是真正的实例…...

记录一下在Pycharm中虚拟环境的创建
如果在Pycharm中要新建一个虚拟环境,那你可以在Terminal中选择Command Prompt,在这里面执行相关命令 一、安装了Anaconda,创建虚拟环境 当你使用解释器是Anaconda提供的时,你可以使用conda命令执行,见以下操作&#x…...
Python从入门到精通秘籍九
一、Python中文件编码概念 在Python中,文件编码指的是将文本内容转换为字节序列的过程。不同的编码方式使用不同的字符集和字节表示形式。下面是一个示例代码: # 写入文本到文件 text "你好,世界!" with open("…...
善于利用window挂在全局变量
开发过程成中遇到一个奇怪的问题,打开一个echats图表之后,关闭echarts图再进入其他页面页面会报错提示 $(...).draggble not a function经过一步步定位,发现echats图是通过后端获取js、css文件然后在本地绘制而成。而获…...

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…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...