6. 网络编程-网络io与select、poll,epoll

https://0voice.com/uiwebsite/html/courses/v13.7.html

首先看看这个学习计划

  1. 网络、网络编程、网络原理
  2. 基础组件,20个。
  3. 中间件 Redis ,MySQL,Kafka,RPC,Nginx
  4. 开源框架(解决方案)业务开发(工程师开发,写代码)
  5. Docker/K8S,产品角度
  6. 开源代码,写的闭源的。
    火焰图,bpf/ebpf
  7. 分布式,分布式DB,分布式fs。etcd
  8. 项目能与公司业务场景(dkvsstore,图床)

在这里插入图片描述
samba配置可以看这个链接

服务器客户端实现

#include<stdio.h>
#include<string.h>
#include<errno.h>#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>int main() {//openint sockfd = socket(AF_INET, SOCK_STREAM, 0);//iostruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr_in));//192.168.2.123servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//0.0.0.0servaddr.sin_port = htons(9999);if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {printf("bind failed:%s",strerror(errno));return -1;}listen(sockfd, 10);getchar();}

然后我们运行:

gcc -o multi-io multi-io.c
./multi-io

然后他会阻塞住:
在这里插入图片描述
在这里插入图片描述
然后我们进入一个可视化工具也是可以看的。
在这里插入图片描述
这时候我们已经收到了数据,但是还没有处理。我们上面写的代码就好比一个酒店的服务员。他是可以进去的,但是没有处理。这时候我们要给这个客户端分配一个服务员。

#include<stdio.h>
#include<string.h>
#include<errno.h>#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>int main() {//openint sockfd = socket(AF_INET, SOCK_STREAM, 0);//iostruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr_in));//192.168.2.123servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//0.0.0.0servaddr.sin_port = htons(9999);if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {printf("bind failed:%s",strerror(errno));return -1;}listen(sockfd, 10);#if 1struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);#endifgetchar();//block
}

一开始的代码阻塞在getchar(),我们一敲回车他就会退出,但是现在代码阻塞在客户端接收这部分了。
然后这时候我们在这个工具中一点击链接他就退出了。也就是有客户端连接他就往下走了。
在这里插入图片描述
然后这就引出一个概念,阻塞型IO和非阻塞型IO,阻塞型IO就是等待连接,没有连接就是一直等待着,等待条件满足了之后才往下走。
下面是非阻塞IO:

#include<stdio.h>
#include<string.h>
#include<errno.h>#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>int main() {//openint sockfd = socket(AF_INET, SOCK_STREAM, 0);//iostruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr_in));//192.168.2.123servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//0.0.0.0servaddr.sin_port = htons(9999);if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {printf("bind failed:%s",strerror(errno));return -1;}listen(sockfd, 10);sleep(10);
#if 1int flags = fcntl(sockfd, F_GETFL, 0);flags |= O_NONBLOCK;fcntl(sockfd, F_SETFL, flags);struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);printf("clientfd:%d", clientfd);
#endifgetchar();//block
}

在这里插入图片描述
然后我们现在实现代码接收数据并且返回数据。

接发消息

#include<stdio.h>
#include<string.h>
#include<errno.h>#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>#define BUFFER_LENGTE   1024
int main() {//openint sockfd = socket(AF_INET, SOCK_STREAM, 0);//iostruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr_in));//192.168.2.123servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//0.0.0.0servaddr.sin_port = htons(9999);if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {printf("bind failed:%s",strerror(errno));return -1;}listen(sockfd, 10);//sleep(10);
#if 0printf("sleep\n");int flags = fcntl(sockfd, F_GETFL, 0);flags |= O_NONBLOCK;fcntl(sockfd, F_SETFL, flags);
#endifstruct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);printf("accept\n");char buffer[BUFFER_LENGTE] = { 0 };int ret = recv(clientfd,buffer, BUFFER_LENGTE,0);//接收数据printf("ret: %d,buffer:%s\n", ret,buffer);send(clientfd, buffer,ret,0);//将接收的数据在返回回去getchar();//block
}

在这里插入图片描述

这时候发现我们只能发一次。在上面的代码中有两个是阻塞的,一个是accept还要一个是recv,第一个是等待连接,第二个是等待收到消息。

多次接发消息

然后我们在这里引入一个循环,while(1)

#include<stdio.h>
#include<string.h>
#include<errno.h>#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>#define BUFFER_LENGTE   1024
int main() {//openint sockfd = socket(AF_INET, SOCK_STREAM, 0);//iostruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr_in));//192.168.2.123servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//0.0.0.0servaddr.sin_port = htons(9999);if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {printf("bind failed:%s",strerror(errno));return -1;}listen(sockfd, 10);//sleep(10);
#if 0printf("sleep\n");int flags = fcntl(sockfd, F_GETFL, 0);flags |= O_NONBLOCK;fcntl(sockfd, F_SETFL, flags);
#endifstruct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);printf("accept\n");while (1) {char buffer[BUFFER_LENGTE] = { 0 };int ret = recv(clientfd,buffer, BUFFER_LENGTE,0);//接收数据printf("ret: %d,buffer:%s\n", ret,buffer);send(clientfd, buffer,ret,0);//将接收的数据在返回回去}getchar();//block
}

然后这里就可以无线的接收和发送了。
在这里插入图片描述
这时候就又出现一个问题,我们这个代码只能有一个客户端。第二个客户端连接不上。然后就引入下面

多客户端

这里我们可以引入多线程

#include<stdio.h>
#include<string.h>
#include<errno.h>#include<pthread.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>#define BUFFER_LENGTE   1024void* client_thread(void* arg) {int clientfd = *(int*)arg;while (1) {char buffer[BUFFER_LENGTE] = { 0 };int ret = recv(clientfd, buffer, BUFFER_LENGTE, 0);//接收数据printf("ret: %d,buffer:%s\n", ret, buffer);send(clientfd, buffer, ret, 0);//将接收的数据在返回回去}
}int main() {//openint sockfd = socket(AF_INET, SOCK_STREAM, 0);//iostruct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr_in));//192.168.2.123servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//0.0.0.0servaddr.sin_port = htons(9999);if (-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {printf("bind failed:%s",strerror(errno));return -1;}listen(sockfd, 10);//sleep(10);
#if 0printf("sleep\n");int flags = fcntl(sockfd, F_GETFL, 0);flags |= O_NONBLOCK;fcntl(sockfd, F_SETFL, flags);
#endifstruct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);printf("accept\n");while (1) {int clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &len);
#if 0		char buffer[BUFFER_LENGTE] = { 0 };int ret = recv(clientfd,buffer, BUFFER_LENGTE,0);//接收数据printf("ret: %d,buffer:%s\n", ret,buffer);send(clientfd, buffer,ret,0);//将接收的数据在返回回去
#elsepthread_t threadid;pthread_create(&threadid, NULL,client_thread, &clientfd);//线程id,线程属性,线程的入口函数,入口函数的参数#endif}getchar();//block
}

在这里插入图片描述
注意这里执行的时候要输入

gcc -o multi-io multi-io.c -lpthread./multi-io

然后我们现在是1请求1线程。但是如果一个线程一个客户端这样代价很大的。然后下面是IO多路复用

IO多路复用

就是找一个秘书将着一堆的IO进行管理:
在这里插入图片描述
然后这io多路复用有三个东西,

  • select
  • poll
  • epoll
  • io_uring

select实现io多路复用

select(maxfd, rfds, wfds, efds, timeout);

五个参数,
第一个是maxfd,通过这个maxfd检测那些可读可写
第二个是rfds是可读的集合
第三个是wfds是可写的集合
第四个是efds是出错的集合
第五个是多长时间问一次
这个怎么理解呢,就是这里一共有50个io,这个select就像一个秘书一样,看看那些io是需要写的,那些io是需要读的。比如说这里有10个io是需要可读的那么这10个就是rfds集合。20个io是需要可写的,那么这个20就是wfds。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/706160.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Idea离线情况下安装vue.js插件

亲践有效&#xff0c;步骤如下: 1. 互联网环境登陆vue.js官网(Vue.js - IntelliJ IDEs Plugin | Marketplace)。 2. 然后先确定你的IDEA的版本&#xff1a;在你IDEA的安装文件中找到product-info.json&#xff0c;里面的buildNumber记录着你IDEA的精确版本号&#xff0c;根据…

SMB攻击利用之-mimikatz上传/下载流量数据包逆向分析

SMB协议作为windows环境下最为常见的一种协议,在历史上出现过无数的通过SMB协议进行网络攻击利用的案例,包括针对SMB协议本身以及通过SMB协议实施网络攻击。 本文将介绍一种通过SMB协议的常见利用方式,即向远程主机传输mimikatz,作为我的专栏《SMB攻击流量数据包分析》中的…

Docker 的 RHEL 操作系统镜像

CentOS 和 Fedora 都是和 RHEL 同源衍生版本的 Linux&#xff0c;因为 CentOS 不需要向 RHEL 支付企业级的版权和费用&#xff0c;但是又具有和 RHEL 相同的稳定性和资源库。 所以 CentOS 在服务器上被广泛的部署和使用&#xff0c;但是 CentOS 目前已经停止技术支持和结束了生…

开源的图形化Windows软件安装升级方案:WingetUI

WingetUI&#xff1a;简化数字生活&#xff0c;WingetUI让软件管理轻松便捷- 精选真开源&#xff0c;释放新价值。 概览 WingetUI是在GitHub上开发的一个实用工具&#xff0c;专为Windows用户设计&#xff0c;旨在为常见的命令行包管理工具&#xff08;如Winget、Scoop、Pip、…

二.使用PgAdmin连接Postgresql

二.使用PgAdmin连接Postgresql PostgreSQL是一种开源的对象关系型数据库管理系统(ORDBMS),它支持大部分SQL标准并提供了许多高级功能,例如事务、外键、视图、触发器等。PostgreSQL由PostgreSQL全球开发组维护和开发,它是一种高度可扩展的数据库系统,可以在各种操作系统…

强化学习的优化策略PPO和DPO

DPO DPO(直接偏好优化)简化了RLHF流程。它的工作原理是创建人类偏好对的数据集&#xff0c;每个偏好对都包含一个提示和两种可能的完成方式——一种是首选&#xff0c;一种是不受欢迎。然后对LLM进行微调&#xff0c;以最大限度地提高生成首选完成的可能性&#xff0c;并最大限…

数字水印 | 奇异值分解 SVD 的定义、原理及性质

目录 1 为什么使用 SVD&#xff1f;2 SVD 的定义是什么&#xff1f;2.1 特征值分解2.2 奇异值分解 3 如何求解奇异值 SV&#xff1f;3.1 求解过程3.2 证明过程 4 什么是 SVD 的性质&#xff1f; 参考博客&#xff1a; Python 机器学习笔记&#xff1a;奇异值分解&…

读人工智能时代与人类未来笔记04_理性时代

1. 理性时代 1.1. 康德在《永久和平论》一文中带着些许的怀疑主义提出&#xff0c;和平可以通过应用达成一致的规则管理独立国家之间的关系来实现 1.2. 理性则借助高等理论物理学的形式&#xff0c;开始进一步探索康德的“自在之物”&#xff0c;并产生…

为什么买的蓝牙串口模块不能实现蓝牙键盘给手机文本框或记事本打字或控制手机?

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言1、原因2、蓝牙键盘制作流程 前言 送给大学毕业后找不到奋斗方向的你&#xff08;每周不定时更新&#xff09; 【…

海狐外卖多商户O2O商城系统前端技术实现与探索

摘要&#xff1a; 随着外卖市场的快速发展&#xff0c;多商户O2O商城系统成为餐饮行业数字化转型的重要工具。本文基于海狐外卖多商户O2O商城系统的前端技术实现&#xff0c;探讨了前端技术在高并发、多端适配、自定义装修等方面的应用与挑战&#xff0c;并分享了系统前端架构…

5万字带你一文看懂自动驾驶之高精度地图前世今生

在讲解高精度地图之前&#xff0c;我们先把定位这个事情弄清楚&#xff0c;想明白&#xff0c;后面的事情就会清晰很多&#xff0c;自古哲学里面讨论的人生终极问题&#xff0c;无非就三个&#xff0c;我是谁&#xff0c;我从哪里来&#xff0c;我要去哪里&#xff0c;这里的位…

工作高效记事软件是什么 好用的高效记事软件

阳光斜洒在办公桌上&#xff0c;我埋头于一堆杂乱的文件中&#xff0c;头脑里充斥着各种待办事项。电话铃声突然响起&#xff0c;是老板打来的&#xff0c;提醒我下午三点有个重要会议。挂断电话后&#xff0c;我赶紧拿起笔想在便签上记下&#xff0c;却发现桌面已经被各种便签…