- 博客(187)
- 收藏
- 关注
原创 6.C语言函数
int z = 0;z = x + y;return z;int b = 0;//输入return 0;//如果n是奇数就返回1//如果n是偶数就返回0//return 1;////写一个函数打印1~n的数字//if (n < 1)return;//函数提前返回,提前结束int i = 0;for (i = 1;i <= n;i++)
2025-11-23 21:42:15
303
原创 5.C语言数组
strlen:算的是我们对应的数组\0之前的元素(不含\0),sizeof(arr1)/sizeof(arr1[0]):算的是数组的长度。但是遍历的效率太低了。
2025-11-22 21:19:53
264
1
原创 27.epoll(三)
我们这里使用的是用户空间用于我们文件描述符的传递,事件通知用我们对应的eventfd。我们使用管道,既可以唤醒对应的Reactor,也可以唤醒对应的条件变量。每次发送消息和接收消息,都进行更新时间(这样我们就能做连接管理了)有任何一个请求到了,Master进程不做任何的处理,直接通知子进程。由一个Master创建多个子进程,然后用管道进行通信。我可以用以前的客户端来向我们的服务器进行发起请求。我们要将给文件描述符的关心事件全部都进行更改。epoll啥都能进行关心(包括管道)
2025-11-21 17:03:55
299
原创 27.epoll(二)
IOService只是进行连接的获取,而我们对应的Listener只是进行连接的建立,处理信息式交给我们对应的上层的。我们虽然将一轮全部都读取完了,但是我们还不能确定报文是否读取完整了(所以我们要引入对应的协议)上面的整体我们已经完成了,所以现在我们对应的矛盾就转移到了对应的IOService了。这个是关于我们对应的epoll模型的,不进行改变。上一篇博客的代码我们将会进行一些微调。那么我们如何发送数据呢?这里我们将方法抽离出来。
2025-11-21 11:28:31
532
原创 27.epoll(一)
(LT模式)水平触发模式: 只要底层有数据,就一直告知上层,条件是就绪的(ET模式)边缘触发模式: 当收到新的数据是就会通知对方一次!(从无到有,从有到多,变化(增多)的时候,才进行通知对方)所谓的张三就是我们对应的 (epoll && LT),快递就是我们对应的数据,小车就是我们的输入缓冲区打电话就是我们的通知机制所以ET单位时间内,IO吞吐量更多但是ET这样做是有代价的!!!
2025-11-20 22:34:33
738
原创 26.poll
poll就和select是一样的poll将我们的事件全部都定义出来了(本质上就是宏)我们主要就是看对应的POLLIN(读事件) 和 POLLOUT(写事件)而那个short就是我们对应的位图。
2025-11-19 16:50:43
314
原创 25.多路转接select
输出型参数,表示几秒内进行阻塞如果一个fd只关心读,就将fd添加到读fd_set里面,以此类推用结构体进行包装,就能避免我们因为传参,导致的数组降级之类的情况发生我们来大概看一下我们对应的fd_set的大小。
2025-11-19 15:00:57
562
原创 23.NAT,代理,内网穿透
网络层,是提供了对应的路径选择的能力真正干事的就是对应的各个主机的数据链路层RARP是mac转IP,所以这个非常容易,直接向该主机发送对应的请求,将其IP进行获取即可1.应用层进行序列化成为对应的字符串,向下交付到TCP发送缓冲区2.到了TCP缓冲区,根据一系列的流量控制等操作,将其划分成几个数据段3.向下添加TCP报头,再向下添加IP报头,再封装mac帧,然后进行发送4.到底目标主机,然后进行解包和分用,一直向上进行交付5.以流式将我们对应的有效载荷拷贝到接收缓冲区中。
2025-11-18 15:35:29
288
原创 22.数据链路层
网卡有一种混杂模式,可以将所有的数据直接全部都进行上传(后续再讲)进行碰撞检测,然后再进行碰撞避免(主机进行休眠一段时间)这个局域网就相当于是临界资源,然后碰撞检测和碰撞避免就是保护临界资源的一种方式(类似于锁的功能)
2025-11-18 09:22:59
206
原创 21.网络层
局域网进行通信,本质是数据链路层来进行的IP就是将数据进行转发,但是伴随着丢包的风险,但是TCP会进行超时重传,一次丢包没关系,那就再进行传递TCP解决的是通信策略的问题,IP解决的是具体的转发的问题,两个共同合作,可以进行主机之间的数据转发。
2025-11-17 17:29:31
469
原创 19.传输层协议UDP
16为UDP长度 = (UDP首部(8字节) + UDP数据(报文))如果,打游戏的时候,需要快速传递信息,就算网络波动导致丢包也没事。UDP不可靠不是缺点,而是特点(有时候,我们就需要简单通信)
2025-11-16 11:36:27
250
原创 18.HTTP协议(三)
如果有公司层面进行保证我们的通信安全,我们可以省去对应的加密过程,通过http,以便于我们更快的进行通信。后续的操作,就是在我们的Login里面进行Request和Response之间的操作了。请求ip的变化,用户行为等变化,可以将我们的session进行失效,进行重新登录。这样上传传入的/login的时候,就自动到我们对应的Login()中了。这样我们每一次进行请求的时候,都会自动携带我们的Cookie。如果我们不带我们的Cookie的话,我们就要一直进行身份验证。
2025-11-15 22:13:17
1138
原创 18.HTTP协议(二)
我们现在是任何的访问内容都是给其返回一个字符串,浏览器自己可以进行解析(图片还是文本),但是我们的返回字段中,要加上对应的内容信息。对于浏览器和服务器的http版本来说,一般是不同的,我们传递消息时,一定要将该版本进行交换。当用户只请求我们对应的首页或者/,那么就直接变成默认的index.html。对于我们的返回信息,要包含状态码和对应的状态状态码对应的string值。我们通过图标来去向浏览器发送新的请求,是通过前端的<a>标签进行的。所以,我们在收到对应的信息的时候,我们应该加上我们的默认页面路径。
2025-11-15 16:16:38
1147
原创 18.HTTP协议(一)
应用层协议往往和端口号是强关联的,比如说http(80),mysql(3306),所以我们不需要体现这个端口号浏览器会自动添加端口号当服务器端得到了对应的URL的时候,要将字符重新进行decode(解码)
2025-11-14 21:08:40
311
原创 17.TCP编程(二)和序列化
要使用的时候,我们直接查就行了private:int _x;int _y;char _oper;private://结果int _code;//出错码,0,1,2,3,4。
2025-11-14 11:54:50
1057
原创 17.TCP编程
目前我们的TCP代码和UDP代码,只有创建sockfd时,是不一样的(SOCK_STREAM和SOCK_DGRAM)但是我们来一个用户,创建一个进程,但是进程创建的成本太高了,我们可不可以替换成多线程呢?对于我们的线程池,比较适合处理短任务,或者是用户量较少的情况(因为线程池的个数是固定的)我们如果创建多线程进行通信的话,我们不需要关闭文件描述符表。我们目前写的是一个单进程的程序,所以只能由一个人来发消息。read来读取,write来写(和文件一样)TCP是面上字节流的,所以我们可以直接使用。
2025-11-13 16:23:35
671
1
原创 16.udp_socket(三)
public:nocopy(){}当我们的服务器不想被拷贝,我们可以进行继承上面的nocopy的类即可//表示本地主机public:nocopy(){}public:// 1.创建套接字// 2.1 bind :: 设置进入内核中if(n < 0)if(n > 0)//1.消息内容 && 2.谁给我发的") == 0)//移除观测者message = cli.Addr() + "# " + "我走了,你们聊!
2025-11-12 21:02:19
413
原创 16.udp_socket
对于我们的client,我们就不进行封装了,我们就直接进行对应的实现即可(有时间的可以尝试实现封装)所以这里的客户端由我们对应的OS自动进行随机bind(不用被别人知道)所以,我们的服务器根本就不需要ip,只要一个port来标识唯一性就行了。bind的本质就是将我们对应的_sockfd设置进入内核中。打印对应的发送消息的客户端的IP + 端口。后续我们的网络转主机,就使用这个。返回值为一个文件描述符。
2025-11-11 22:39:45
588
原创 14.封装线程池 和 线程结束
当线程在条件变量下等待的时候,是不能进行Join的。加了锁,忘记释放,又加了锁(这时一直在锁上等待)我们要有一个新的static的锁来保护这个单例。但是单例会不会被多个线程调用呢?但是每一次都要进行加锁的话,效率就比较低了。这样就将大部分线程拦住在第一个if下面了。单线程可能产生死锁吗?上面的构造不用返回值。
2025-11-10 19:03:38
405
原创 14.日志封装和线程池封装
这里定义宏的好处:在该文件进行调用时,会将代码进行宏替换到对应的文件,然后__FILE__和__LINE__就能识别是哪个代码的哪一行int main()return 0;NEW,RUN,STOPprivate://这个地方不能写成成员方法// {// }t->_func();if(n!= 0)if(n!= 0)if(n!
2025-11-10 16:41:38
924
原创 12.线程同步和生产消费模型
这里如果是单生成单消费,那么就没有问题,但是如果是我们对应的多生产和多消费,那么这样就行不通了,因为我们唤醒,是要将所有的代码进行唤醒,而不是只进行唤醒一个线程。答案是生产者,所以当我们进行生产的时候,就将等待的消费者进行唤醒(前提是要有消费者),生产者等待时也同理。这里我们创建了2个生产者,3个消费者(我们刚刚改了while,所以支持多生产多消费了)所以的线程互斥,线程同步的机制,都在我们对应的Equeue和Pop里面进行完成。所有,我们可以加上两个成员函数,来统计我们的生产者和消费者等待的个数。
2025-11-09 19:16:17
980
原创 12.线程同步与互斥
/临界资源//锁本身是全局的,那么锁也是共享资源//加锁//1.抢票//解锁elsebreak;int main()//1.构建线程对象i < NUM;i++)//2.启动线程//3.等待线程return 0;但是锁本身就是临界资源,那么谁保证锁的安全呢?加锁和解锁被设计成为原子的(本身就是原子的)如何看待锁呢?二元信号量就是锁!加锁的本质就是对资源展开预定!整体使用资源!如果申请锁的时候,锁被别人已经拿走了,怎么办?其他线程要进行阻塞等待。
2025-11-09 14:42:17
857
原创 12.线程控制
线程是进程的一个执行分支,线程在做任何事情,就是进程在做,野指针本质就是查询页表失败,然后MMU报错,CPU内部触发软中断,根据软中断的中断号处理中断向量方法,给目标进程发送信号。我们拿到的只是FILE*(前面博客里有我们自己实现的简单stdio的库,那个里面的FILE,就是我们自己进行维护的)所有的线程都能看到我们任意的一个方法(函数),全部的线程数据共享,代码也是共享的。多线程中,所有的资源都是共享的(独立的栈,但是想访问也是有方法的)答案是不行的,因为程序替换,会将代码进行替换,导致其他的线程奔溃。
2025-11-08 14:47:48
886
原创 12.线程(二)
TLB缓冲的是虚拟到物理地址的映射,cache缓存的是代码和数据块(进程间切换,前面都会失效,但是线程间切换不会失效)也就是说,我们有一个创建一个轻量级线程,只要给这个线程一个函数的入口地址就可以了。pthread库属于第三方库,我们要加对应的-l选项。直接执行中断逻辑(默认处理方法),然后将其处理即可。重复的访问,就可以进行优化,减少时间消耗。然后从MMU里面出来的就是物理地址。硬件快,所以要硬件自动完成。线程创建的个数一般都等于。
2025-11-07 17:29:29
271
原创 12.线程(一)
应该子进程退出的时候,系统默认对其的信号是Ign的,所以我们看不到对应的反应所以,现在我们对应的子进程退出时,确实会给父进程发送信号,我们就能基于信号,来进行回收子进程。
2025-11-07 11:38:59
333
原创 11.Linux进程信号(三)
将系统调用号,放到寄存器中,然后触发系统调用(int $0x80),然后自动查表,执行对应方法本质上系统调用就是为了提供安全的访问环境。
2025-11-06 21:06:27
1163
原创 11.Linux进程信号(二)
我们不需要对pending表进行修改,因为,pending表不需要被修改(上篇博客(ctrl + c,ctrl + \等)全部都是修改我们的pending表的)同理,我们的handler表,也不需要进行修改,因为我们的signal()函数就是进行修改handler表的。我们看到这里的1成功显示出来了,但是因为,我们的2号信号被屏蔽了,虽然到达了,但是进程还是在跑的。信号屏蔽解除了,所以,我们的pending表的位置还是1,执行默认的操作,然后就退出了。所有的内核区的数据,全部都是用的一块页表进行映射。
2025-11-06 17:25:28
644
原创 11.Linux进程信号(一)
这里默认将core进行关闭的,但是如果进程出错了,那么就会重启(这样就一直出错,一直重启),那么哦我们的磁盘上很容易被打满core.xxx。OS不会处理Eflags,只会处理信号,所以Eflags里面的标志位一直都是1,所以就是死循环。所以,我们就知道了,对于我们的信号有默认的处理方式,并且我们还可以设置相关的信号处理方式。我们的新一点的服务器,只会生成core(避免一直生成core.xxx,一直只有一个)如果我们将所以的信号全部都进行捕捉,那是不是我们对应的进程就永远都杀不死了?
2025-11-06 13:01:11
1068
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅