- 博客(135)
- 收藏
- 关注
原创 Reactor
非阻塞一直循环读取的时候,如果出错了,但是errno 错误码 如果等于 EWOULDBOLCK,说明这次读,一直读 读出错了,表明把本轮数据全读完了,读完了我们就不处理了,所以直接break就可以了。普通的事件就绪他就会检测是否是读事件还是写事件,连接是否是健康的,然后直接执行曾经绑定的方法,对于普通的文件描述符,他绑定的方法刚好是它曾经设置的回调,也就是刚刚绑定的Recver。你知道你要把数据处理的时候,从connection里面怎么读吗,我们调recv就可以读,我们曾经添加这个fd已经设置为非阻塞了,
2024-12-19 17:44:49
874
原创 高级I O
今天要发数据,本质上是发送缓冲区要有足够多的空间,如果没有足够空间你也就没办法把数据从应用层拷贝到内核层。先读为例,今天我调用read,tcp套接字,可是底层接受缓冲区里没数据,默认read就阻塞式的等待。今天我想写入,但是发送缓冲区已经被打满了,上层无法把数据拷贝到下层,write也就必须阻塞式的等。几乎所有的提高IO效率的策略,本质就是==单位时间内让等的比较越小!因为多线程可以同时等待多个fd,所有 的IO等待不是串行的而是并行的,等的比重减小了。今天网络也属于IO,本质就是把数据从计算机导到网卡。
2024-12-16 13:53:46
413
原创 网络原理done
根据IP地址,因为局域网中所有主机的IP地址是不一样的,所以主机B就会根据IP地址区分有人向我发起ARP请求,主机B识别到之后就说,主机A你好我是IPB,我的MAC地址是MACB,定向的把响应报文返回去。主机A会在以太网中广播一条消息,消息内容是我是主机A我的IP地址是IPA,我的MAC地址是MACA,我要找一台主机他的IP地址是IPB,我不知道他的MAC地址你们谁是把MAC地址给我。主机A 会发送ARP请求,以广播的方式第一次发的时候,构建MAC帧广播目的地址被填成全1,16进制就是全F。
2024-12-15 12:34:30
278
原创 ip_done
1.公司是不是这样呢?类似的要给运营商交钱,构建公司的子网,具有公司级别的入口路由器2.为什么要这样呢??IP地址不足我们可以使用相同的内网IP来让更多的主机接入到了网络,你甭管我是接入的运营商的内网还是广域网,反正我能让你上网就行了。所以NAT主要用来解决IP地址不足。
2024-12-14 11:39:33
597
原创 ip 协议
所以呢无论是文件中,还是网络套接字里,还是未来tcp udp的套接字里,各自提供各自层的方法,tcp,udp根本不会把数据send发送到网络里,他应该把数据交给下一层,所以对应的所有函数指针指向的方法由对应的协议栈给我们提供方法集。未来file提供的方法一部分直接指向网络方法了,file方法最终要解决的是对上的问题,因为用户数据在应用层,应用层数据一定要通过fd拷贝到我们的套接字所对应的接受和发送队列中,他要给你形成一个节点,把他连入到队列中。Linux内核是用C语言写的,所谓的协议栈本质就是。
2024-12-11 18:31:29
496
原创 TCP 2
如果一个客户端来向我建立连接时,如果三次握手能完成,服务器就在底层建立好连接,连接可以暂时不把他拿上去,底层是能够把链接建立好的,第二个客户端再来的时候呢,三次握手一旦完成,OS也一定要在建立连接,此时如果有第三个第四个,如果服务器允许你把链接建立好,那么S上一定会存在大量的已经建立好的连接,但是已经建立好的连接并没有被上层accept拿上去,所以我们的OS就必须起一个对已经建立好的连接进行临时维护的效果,要对这些没有被拿上去的连接管理,所以先描述在组织,它采用队列的形式来管理已经建立好的连接,
2024-12-09 11:01:13
633
原创 T C P
UDP,tcp这样的协议根本不是直接谈UDP。tcp的应用场景,一定是上层写了应用层协议,所以才有UDP协议的应用场景。比如http。
2024-12-06 20:18:33
466
原创 UDP协议
你无法通过管道交给kill -9直接杀,你得用xargs来杀,因为Kill -9 pid ,kill是可执行程序,-9 pid是命令行参数,管道把一堆Pid以标准输入的方式交给Kill是不行的,必须要xargs来交给命令行参数,此时就可以批量化删除。不谈应用层如何序列化,反序列化,应用层都不考虑,单纯站在两个主机通信角度,我们是需要五元组的,分别由不同层不同协议来给我们提供对应的字段,提供对应的功能,来保证通信的正常。那两台主机要通信,那两个进程要通信,通过什么协议来通信,我们就可以把他们标识清楚了。
2024-12-06 14:26:54
676
原创 HTTPS
比如黑客和你不是同一个地区的,此时服务器甄别到你账号有异常,人家把session信息设置为暂停状态,并让用户重新登录,如果登录失败了立马把这个session删掉,这个sesion就不奏效了。浏览器中的cookie文件就会保存这个session id,此后每次请求都挟带这个ID,如果存在于服务端就服务,不存在就重定向到网站首页重新登录。如果你上了一些不好的网站,黑客可能在你的机器上开放某些端口,把你的cookie信息就给盗走了,之后他拿着你的账号密码就去登录了。最大的好处是你的私人信息不会被泄露了。
2024-12-03 13:54:02
454
原创 HTTP2
有流量就有钱,几年前最大的搜索引擎比如度,骨骼,但在打开搜索引擎前得先打开浏览器,所有谁掌握浏览器谁就能掌握互联网流量入口,所以浏览器很多。协议就是协议,即使状态码一直是200,浏览器一样能解析,但是协议就是协议,即使别人不做你也要做。状态码必须写,描述也必须有。4xx 网络正常,Brose Server或CS 要不是客户端错,要不是服务器出错。POST提参也能被抓包,也能看到密码,相比get更私密,get的参数会回显到URL。GET方法通过URL进行提参,参数数量受限的,不私密。
2024-12-02 13:37:01
193
原创 HTTP 1
包含协议的名称,登录信息不考虑,服务器地址就是域名,端口号冒号80所以可以省略因为协议已经默认了就像火警号一样,端口号80后面的/,当你看到/的时候linux中路径分隔符就是/,也能间接证明这个资源所在的位置有可能是在Linux服务器上的。所以从此往后,我们在公网服务器上每一个资源都有唯一的一个字符串路径,这个路径是唯一的,区分和其他主机之间的区别是通过域名来区分的,哪些资源哪些进程应该访问呢由端口号帮我们指明,服务器上有不同路径,每个字段都具有唯一性。1.网络通信访问资源都是通过URL定位某一个资源。
2024-11-29 12:17:05
494
原创 自定义协议,序列化反序列化
所以OS属于内核,你所谓的用户把数据交给TCP这句话有点不太可信,实际上是用户把自己的数据交给了OS了,那你放心OS吗,当年讲文件操作时,其实是把用户的数据拷贝到文件的缓冲区里,最后由OS来把文件缓冲区的数据定期刷新到磁盘,如果你不相信OS,为什么当年你要相信呢?正确对文件读写,对管道读写,对网络读写,尤其是面向字节流,你怎么保证你读上来的是一个完整的报文呢?TCP是面向字节流的,你怎么保证,你读取上来的数据,是‘’一个“ “完整””的报文呢?所以用户把数据交给TCP,是用户把自己的数据交给了OS!
2024-11-26 14:56:23
284
原创 TCP socket api详解 续
理论上也要退的,但实际上关了bash,bash肯定要退,所有进程的父进程都是bash他就自动托孤,但他们依旧属于同一个会话,所以后台会话还是在系统里被保留下来了,他是没有问题的依旧可以跑的。因为它的父进程直接就退了,所以守护进程立马要被系统领养,他唯一和孤儿进程不一样的是他很坚强,他把自己设置为独立的会话。所以和曾经打开的bash会话中从包含关系变成并列关系,此时你爱怎么样怎么样和我无关,不再受用户登录和注销的影响了。注销:Windows中也有类似会话,注销会把会话关闭,前后台会话都关闭,再重启就不卡了。
2024-11-25 15:03:01
654
原创 TCP socket api详解
将套接字设置为监听状态,他才能随时听到有客户来连我了,然后我就可以帮我们把连接获取上来,然后基于连接再通信。因为TCP是一个面向连接的服务器,在正式通信之前,他一定得随时随地等别人先和我连接上再说。创建套接字socket + sockaddr_in结构体 + bind。也就是通信前得先建立连接,服务期就得一直想办法等别人来连。之后就和UDP不一样了。
2024-11-23 12:12:56
502
原创 udp_socket
有了对应的套接字之后未来就可以使用套接字来进行收发消息,但在进行各种收发之前,我们的服务器都必须得有一个参数socket的返回值,这个套接字创建之后呢,类比文件接口,把文件创建好得到了文件描述符,从此往后所有接口想对文件交互访问都得有fd,套接字的文件描述符同理。socket返回依旧是一个文件,所以创建套接字的本质,底层就是打开一个文件,以前strcut file指向的是具体某一个磁盘上的设备,只不过我们的struct file指向的底层网卡设备,他就相当于一切皆文件。
2024-11-20 13:51:31
973
原创 进程池的子进程的清理工作问题
继续创建子进程建立管道 0 2,0依旧是子进程的读端 ,但是此时子进程的fd表中的1是继承了父进程的1写段,也就是让子进程中有写段指向了第一个子进程,此时第一个管道就有两个写段,继续创建第三个子进程又会继承父进程的fd表 ,就会导致第一个管道写段越来越多。根据管道的四种情况,我们让写端关闭,读端就会读到0,此时break,子进程就会走到exit结束进程。是正常的,父进程利用pipe来打开读写fd,因为父进程要写端,关闭读端,也就关闭了3。为了方便,这里是直接忽略了0,1,2标准输入输出流。
2024-11-16 18:30:46
276
原创 算法-双指针
从暴力枚举法出发 推出 如何 优化 例如:三数之和中 无序的暴力枚举会选出诸如【1,0,1】【1,1,0】这类,对原本数组排序就可以剔除掉重复项,既然有单调性也就是排了序就想到双指针 or 二分。单调性 也就是 数组排序 想到 双指针 或 二分。反向双指针 - 模拟。
2024-10-10 22:01:34
165
原创 【网络基础一】几乎不讲任何网络协议细节,搭建网络基本结构
计算机里因为数据经过长距离传输,所以沟通的成本就高了,距离变成,信息传输衰减是问题,传递过来的信息我得知道这信息是什么意思,所以长距离传输是需要定一些协议的。例子:你去上大学,老爹在老家有一部座机,你给家里打电话 响铃一声,2声,三声,你和老爹约定好了这三种情况都是啥意思,这个东西就叫做协议。我们实际生活中收快递,假如你买了一个洗面奶,可是你会收到多出来的快递盒子,盒子上的各种信息字段,这个多出来的信息字段就叫做协议的报头。我们认为在你家里就是一个局域网,如果你访问自己的服务器,那么就是访问广域网。
2024-08-07 13:13:23
433
原创 lambda
在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。[ ]:捕捉列表里面可以传值捕捉,引用捕捉,捕捉上下文中的变量放进lambda函数中使用。mutable:lambda函数里变量默认是const,次关键字取消常性,不用就不写。->returntype返回值类型:函数返回值类型,一般可以由编译器推导,可以不写。lambda的类型是一个唯一的随机值,class之类的。,可调用对象分为三种,函数指针,仿函数,lambda。():参数列表也就是普通函数的参数,不需要可以省略。
2024-04-29 17:03:06
195
原创 智慧指针底层实现及其使用注意
为什么要有智慧指针?当抛出异常时,程序会立即跳转到匹配的 catch 块,跳过 try 块中剩余的代码。因此,在 try 块中分配的资源(如动态内存、文件句柄等)可能不会被正确释放。为了避免这种情况,可以使用智能指针(如 std::unique_ptr 和 std::shared_ptr)和 RAII(Resource Acquisition Is Initialization)技术来确保资源在异常发生时得到正确清理。智能指针 说白了 就是 指针管理那他是怎么管理的呢?
2024-04-28 16:39:46
267
原创 线程安全的单例模式
先描述在组织 本质就是一套面向对象的思想,大部分语言都支持面向对象,这就是语言设计者发现都 大家使用时都一样,都需要面向对象,他不是语言必要的特征,他是计算机发展必然的阶段,大家刚开始你是你我是我,二进制,汇编,C的,VB VC。因为后面网络服务器希望它是单例的,一个服务器一旦启动了那就一个启动就行了,不需要再用它的类创建更多的对象了。另外线程池我也不想过多创建,一会总结线程池优缺点,再来谈一谈为什么要把他改成单例模式。编代码也是有方式的,发展这么多年大神们最后大家的代码都很类似,最后总结出一套模板,
2024-04-20 12:51:24
652
原创 线程池 1-17续
调系统调用也是有成本的。比如申请内存,一次多给你一点,间接减少系统调用次数。单例模式设计线程池涉及的加锁双if问题 饿汉 懒汉。所有的池化技术本质都是以空间换时间。C++类内创建线程原生线程。
2024-04-19 17:50:49
174
原创 配置vscode链接linux
4. 切换到远程资源管理器中 应该可以看到一台电脑,右键在当前窗口链接,输入你的服务器用户密码后电脑变绿说明远程连接成功。3. 选择保存远端host到本地 某位置 等待片刻后。5.一定要登陆上云服务器后再安装各种插件。1.安装 remote SSH。ssh ljh@服务器公网ip。
2024-04-06 15:27:03
334
原创 为什么uint16_t的范围是0~65535?
因为C1n = A1n啊,所以只要是只选出一个的,不管每个位置有几种可能排列还是组合都一样。每一位密码只有两种可能,按照乘法原理你要每一位都选出来才可以,所以是 2^4=16种可能。两个可能选一个出来,应该是C12,至于A12感觉他们在这个问题上是一样的。每一位只有两种可能,每位选出一个 一共有2^16 = 65536个组合。那天我改密码,如果你的密码是例如+ - + -这样的四位密码。也就是全0 ~ 全1 则范围是 0 ~ 65535。也就是0000 0000 0000 0000。
2024-03-05 19:58:55
401
原创 【网络 】
netstat -n(显示数字)au(all udp)p(显示pid信息)查内网ip 和 以太网mac地址。netstat 网络状态。
2024-01-27 13:35:58
141
原创 死锁 + 条件变量 + 生产消费者模型
线程第一次申请锁成功,继续再次申请,第二次申请就失败了,当前线程抱着锁就被挂起了。现象 : 代码不会继续往后推进了。一把锁有没有可能产生死锁呢?3. 剩余线程申请锁都不成功。其他线程申请都失败阻塞了。所有整个线程全部都卡住了。1.你抱着锁去休眠了。
2023-12-16 13:22:53
609
原创 【加锁 】
1.从逻辑上不对,因为你难道想让一个线程在while循环中,一个线程把票全抢完然后才能到下一个线程抢吗,下一个线程抢都没票了。线程申请锁失败了,线程阻塞等待的本质是线程等待锁资源不就绪,调度器把线程PCB阻塞后去锁的队列里进行等待。此时解锁代码没有被执行,这个线程已经走了,但是锁一直没释放,其他线程会一直阻塞。但是这里还有问题,可能一个线程抢到锁了,在抢票时发现票没了直接break。我们要把对应的资源保护起来,要保证多个线程申请的是同一把锁。没有拿到锁的线程,就必须要在指定的锁上等待。
2023-12-14 13:25:35
497
原创 线程互斥与同步
用户级线程 和 内核级线程 也就是线程实现真的是在OS内部实现,还是应用层或用户层实现。必定每一个人都要有自己独立的栈结构,让自己的调用链不受别人的。用户级执行流(用户级线程) :内核lwp = 1 : 1。新线程在执行流上和主线程是独立的,所以他们形成调用链时。站在线程角度每个线程都有自己独立的栈结构,但并不是说我。用户级线程 + 内核的LWP = Linux线程。干扰,所以每一个线程都要有自己的栈结构。这个栈不仅仅要简单的变量定义,入栈出战。所以主线程当然要有自己的调用链。下面来谈谈线程库中的栈。
2023-12-11 19:03:32
520
原创 线程控制.
因为main函数和指定函数threadRoutine 它在同一块代码被编译时一定使用代码部分不同的地址空间范围,代码区虽然是一整块,但不同函数用的不同的地址空间,注定了这两个线程执行时在代码资源上是分离的。既然他只有轻量级进程的概念的话,注定了linux os不会给我们直接提供线程的系统调用,只会给我们提供轻量级进程的系统调用!线程已经成为调度的基本单位了,每一个线程都属于同一个地址空间中,所有的线程都属于同一个进程。正是因为OS用进程内核数据结构模拟的线程,所以内核中有没有很明确的线程的概念呢?
2023-12-05 12:34:24
441
原创 线程+地址空间4
如果我今天再创建一个“进程” 不再给它创建新的地址空间,新的页表,我只创建pcb,让其指向父进程的地址空间,也指向父进程的页表(我们不管)我们以前创建子进程,父子进程在数据结构上相互独立,需要给子进程开辟新的pcb,地址空间,页表,虽然大部分都是从父进程来的。此时新的子进程就在父进程的地址空间内运行,同时把页表中对应分出来区域的映射给新的子进程就可以了。既然能创建一个,就能创建多个,只创建pcb,把一个进程的地址空间分成若干份分给子进程部分代码。此时线程的执行粒度,要比进程更细,为什么这么说?
2023-12-03 20:22:20
461
原创 信号收尾.
看看sigaction结构体里面,红线是我们不关心的,里面有个sa_handler不就是之前信号捕捉的函数指针类型吗,也就是处理方法,其实也就是修改了handler表里面的方法。输入型参数act结构体里面包含了你要设置新的动作,输出型参数oact是保存老的设置以便你后续恢复。我们发现函数名和形参中结构体名一样都是sigaction,这在c/c++中允许吗?它也是信号捕捉,不仅能处理普通信号还能处理实时信号,但我们不管实时信号。这个结构体红线你都不关心,那直接用memset都清零就可以。
2023-11-30 12:04:26
469
原创 可变参数列表
demo 2:求任意多个数据中的最大值(至少一个),要求不能使用数组因为目前参数个数不确定,那么函数编写的时候,参数个数也无法确定,换句话说,函数也就没法编写不过,C提供了满足该场景的解决方案:可变参数列表。
2023-11-29 12:41:48
816
原创 信号-重谈地址空间3
信号的保存:我可能正在推高地,脑子里面记住我外卖到了,一会再去拿。信号的产生:外卖小哥给我打电话说你外卖到了。信号的处理:我打完了,下楼把外卖拿了。完成了一次信号的生命周期。
2023-11-23 17:33:45
495
原创 SystemV ipc(进程间通信)
如果今天创建了一个共享内存,OS就会为我们创建struct shmid_ds结构,我们就把第一个字段struct ipc_perm shm_perm地址放入到数组当中,消息队列和信号量同理都把第一个字段地址放入数组中(这个道理就像你创建一个都是Int类型的结构体你看看第一个整形的结构体地址和结构体地址一不一样?数组中保存的是ipc_perm的地址,该如何访问共享内存or消息队列 shmid_ds 和msgid_ds中的其他属性呢?,OS中也是用数组来管理的,数组中保存了struct ipc_perm*
2023-11-22 13:02:35
230
原创 共享内存.
因为不能让进程直接malloc,你这样申请了那这块空间就是你的,会破坏了进程的独立性。OS帮助申请内存,通过页表挂接到进程地址空间中,给应用层返回起始虚拟地址。到了共享内存了支持双向通信能读也能写,但是一般都是一个读一个写。上面的操作都是进程直接做的吗?直接由操作系统来做。进程间通信的本质是:先让不同的进程,看到同一份资源!如果要释放共享内存:去关联,释放共享内存。要想通信先看到同一个份资源,则。3、共享内存的特性,扩展代码。我们要把这句话奉若圭臬一般。
2023-11-21 16:00:48
141
原创 打开文件 和 文件系统的文件产生关联
2、如果4KB文件你只要100字节,你能保证你下一次不用这文件上下文的其他数据吗?反正拿100字节还是4KB效率差不多,因为估摸着你后面的字节大概率也要用。物理内存和磁盘交互的单位是4KB,磁盘中未被打开的文件数据块也是4KB,所以磁盘中页帧也是4KB,内存中叫页框。把数据交换的物理内存也要花4KB?1、和磁盘交互比较慢,一共4KB每次要1KB的效率不如一气直接4KB,因为磁盘只需要定位一次。我这个文件可能没有4KB,就一个字节,但不好意思加载4KB。我这个文件4KB,想修改1字节,也得加载4KB。
2023-11-16 20:24:02
182
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人