- 博客(118)
- 收藏
- 关注
原创 GET&& POST
网络上的大部分请求 都是 GET , 通过 query string 告诉服务器要搜索什么, 服务器返回搜索结果的完整网页.首先, 盖棺定论 , GET 和 POST ,com本质上讲, 没啥区别。POST 使用场景比较少, 常见的有两种场景。POST的用于场景, 使用GET 也可以/.GET 的应用场景, 使用POST 也可以。但从使用习惯上来说, 还是有区别的.
2024-06-16 10:54:52
389
原创 IP协议报文格式
总长度,去掉IP报头长度,就是IP载荷长度,而IP载荷是由TCP/UDP报头+ TCP/UDP载荷组成,所以去掉TCP/UDP报头长度,剩下的就是载荷长度了.IP协自身实现了拆包,组包这样的功能,如果数据包的长度超过上限,IP数据包就会自动拆分成多个数据包,每个数据包携带一部分,发送到对方后,再拼接好.32位范围: 0 - 42亿9千万,原则上.IP地址应该是唯一的,不重复的,但32位仍然不够用,尤其是现在处于移动互联网的今天.一个数据包在分用的时候,要交给上层的哪个协议,都是有明确的声明的,
2024-06-10 23:14:45
1149
1
原创 IP协议(二)
如果不存在,就会从周围的设备中,挑选一个"最神通广大"的设备,吧这个数据交给这个最神通广大的设备,这个最神通广大的设备就会查找自己的路由表中是否存在目的IP,如果存在,直接转发即可,如果不存在,则把数据交给他周围设备中"最神通广大"的设备…以此类推直到找到目的IP.在网络中,路由器的寻路,则无法做到"最优解",只能做到"较优解",因为每一台路由器,无法知道整个网络的"全貌",但是可以知道它附近的设备是咋样的.子网掩码 . . . . . . . . . . . . : 255.255.0.0。
2024-06-10 23:14:23
701
原创 中间代码生成
2.根据所设计的分析程序和所给定的测试用例,自行构造识别活前缀的DFA、ACTION表和GOTO表,上机测试并通过所设计的分析程序。通过设计、编制、调试一个 do-while 循环语句的语法及语义分析程序,加深对。法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。DO-WHILE循环语句的中间代码生成。(3)词法分析生成文件内容截图。(4)语法分析生成文件内容截图。(5)中间代码生成文件内容截图。三. 实验内容及结果。
2024-06-08 19:14:40
283
原创 TCP的核心属性
比如: A和B建立了TCP连接,A这边关机了,A关机之前,告诉B,发送fin,B这边收到了fin,B返回ACK,代码进入下一阶段流程,准备发送fin,但如果A关机了,也就意味着B 接下来的 fin 不会收到ACK,B的fin就会反复重传几次, 如果B仍然没收到ACK,还是继续把A给删除, A都已经关机了,之前保存的B的信息,自然也没了.B给A发了一个心跳包,如果A正常,A就会回应ACK,如果A挂了,B就不会收到任何回应.连续发了若干次,A都没有回应,这个时候B认为A挂了,于是单方面是否连接.
2024-06-05 19:43:13
1469
原创 使用Matlab软件绘制函数图像
1.利用Matlab实现平面上曲线和三维空间中曲线绘制,重点掌握隐函数、极坐标图像绘制的相关命令。2.利用Matlab实现三维曲面绘制,加深对高等数学课程所学内容的理解。
2024-06-05 19:41:41
1382
原创 二叉查找树
(1)实验题目二叉查找树(2)问题描述对于查找集合进行动态查找,为了使得元素的插入、删除和查找操作都能够很快地完成,可以采用二叉查找树作为查找结构。对于给定的查找集合,给出在二叉查找树上进行查找的比较次数。
2024-06-04 08:03:37
470
原创 topK 问题
典型的topK问题,由于题目要求的是最大的前K个数,所以使用小根堆,堆的大小为k,首先创建堆,此时堆的大小为k ,当再次插入元素时,和栈顶元素比较,如果比堆顶元素大,把堆顶元素删除,将该元素入堆;如果比堆顶元素小,不做任何处理.把所有的数据集合遍历完,此时,小根堆中的元素就是最大的前k 个数.,然后再对这k个数求和.if(elem[child] < elem[parent] ),交换child 下标和parent下标的值,然后child = parent ,parent =( child -1) /2。
2024-06-04 08:00:43
976
原创 TCP报头
但TCP报头的长度是可变长的,如果选项完全没有,TCP报头长度就是20个字节,如果选项内容拉满,tcp报头最长就是60个字节(也就是选项部分最多是40个字节)而在TCP报头中,提前申请好一块空间,这个空间暂时先不用,但是以后,如果TCP需要扩展一些新的功能,就可以使用这个保留位来表示了.发送方的数据可能没出错,但校验和可能在传输的过程中出错,这种情况下,接收方仍会把接收到的数据扔了.指的是可选的,这部分内容在报头中可以存在,也可以不存在,4位首部长度指的是报头的长度,而不是总tcp报文的长度.
2024-06-03 22:28:41
553
原创 TCP协议的核心机制
超时:发送方发送数据之后,会等待一定的时间,如果等待时间超过某个"阈值",还没收到ACK,就认为是出现丢包了.出现丢包,就会重传 ,把刚才发送的数据在发送一遍.如果重传的越来越快,但成功的概率比较低,是非常浪费系统资源的.确认应答机制:讨论的是发送方能否把数据发给接收方,发送成功,接收方就会给一个应答,没发送成功,接收方就没有应答,没发送成功就称为丢包了.虽然网络传输的中间过程可能是后发先至,可能是乱序的,但在接收缓冲区里,会对收到的数据先排个序,让序号小的,在前面,序号大的,在后面.
2024-06-03 22:28:04
1163
原创 IP && 端口号
服务器是不能直接通过调试器去调试(调试器一调试就会把服务器阻塞住,无法给别的客户端提供服务了),而是通过网络的方式,给服务器发调试请求,服务器会返回对应的关键信息,这样的端口称为"调试端口"这样的操作,经常会通过网络来进行操作,服务器就会另外绑定一个端口号,称为"管理端口",程序员想对这个服务器进行管理操作,就通过管理端口给服务器发送一些对应的请求,然后服务器就会执行对应的逻辑.把小于1024的端口号拿出来,称为"知名端口号",把这些端口号分配给一些比较知名的服务器程序,作为这些服务器的"默认端口号".
2024-04-30 21:44:19
846
1
原创 UDP!!!
假如全世界都是用同一个操作系统,升级的成本相对来说会小一点.但市面上存在各种各样的操作系统,如果某个操作系统升级了,其他系统没有升级,意味着这个升级的系统和其他系统。比如:电信号表示 0 , 1 ,低电平表示 0, 高电平表示1 ,此时传输的过程中,遇到一一个变化的磁场,此时就可能把本来的低电平变成高电平/高电平变成低电平。(3)不可逆 : 通过原数据,计算 md5 ,成本很低,但通过 md5 ,还原成原来的数据,成本很高,仅仅理论上可行)但升级报头,不是技术上的难题,更多的上政治上的难题.
2024-04-30 21:43:44
1289
原创 开发模型???
用户需求:通常就是一句话,没有经过合理的评估;用户需求不能直接作为开发和测试的依据.针对用户的需求,产品经理需要进行需求分析(技术可行性,市场可行性,成本投入和收益占比等)软件需求:对用户需求进行评估后,可以实现用户需求,往往包含步骤和细节.
2024-04-28 19:16:03
900
原创 网络编程(一)
因为网络环境,太复杂了,A传输给B,中间可能会经历很多的交换机和路由器,而这些交换机和路由器也不只是转发我自己的数据,要转发很多数据.比如:某个交换机/路由器,非常繁忙,繁忙到,要处理的数据量,已经超过了自身的硬件水平限制,此时,多出来的数据,就无法转发,会被直接丢弃掉.对普通文件的操作,就是针对硬盘设备的抽象,直接操作硬盘,能操作,不方便,借助文件这个概念(遥控器),就可以很快的完成了.为了对抗丢包,就引入"可靠传输",TCP就具备可靠传输的特点,内部就提供了一系列的机制,来实现可靠传输.
2024-04-27 20:07:03
519
原创 网络编程!
构造Socket对象的时候,没有指定端口号,没指定并不意味着没有,而是操作系统,自动分配了一个空间的(和别的程序不冲突)的端口号,这个自动分配的端口号,每次启动程序都可能不一样.对于客户端来说,给服务器发送请求,刚才指定的服务器IP,服务器端口号,就是目的IP,目的端口号,源IP,也是客户端所在的IP(127.0.0.1),那么源端口号是什么?1)服务器要有固定的端口号,是因为,客户端需要主动的服务器发送请求,如果服务器端口号不是固定的,(假设每次都变,此时客户端就不知道请求发给谁了)
2024-04-27 20:06:22
514
原创 网络常识!!!
比如:民国时期,有钱人打电话,不用拨号,拿起来就能说话,告诉接线员,给我接xxx的线路,接线员就把一根线拔下来,插到另一个接口上,你就可以和那边打电话了.一个主机上有0-65535那么多端口号可以用,而且是同一时刻,A程序用80 ,B程序此时不能用,但过一会,A结束了,B继续用80,也是可以的.路由器虽然有很多的网口,可以用来插网线,进行组网,但实际上,路由器上面的网口可能不够用,此时就可以使用交换机,对端口进行拓展.端口号能够区分同一个主机上的不同程序,但两个主机上使用的端口号是否一样,无所谓.
2024-04-22 22:14:13
626
4
原创 震惊,原来这就是协议!!!
协议就是一种约定通信双方,对于通信规则的约定,一定是通信双方都认可的.进行网络通信的时候,一定是需要通信协议的,主要是因为:两个用来进行通信的主机设备,可能是不同的硬件,不同的操作系统,不同的应用程序…即使上述内容不同,通信也可以正确的进行.
2024-04-22 22:13:23
857
1
原创 定时器及其模拟实现
比如,现在13:00,老板1给我安排活,14:00开始执行,那么,我可以等待60min,但老板2给吗安排工作,13:30,开始执行,那么我只可以等待30min了,但到13:30就必须立即执行,所以需要通知我,不能让我阻塞等待60min.当前 自己定义的任务中,要保存执行任务的绝对时间(时间戳),为了后续线程执行的时候,可以方便的判定,该任务是否能够执行,如果是保存delay,随着时间的推移,还要更新delay,比较麻烦.一个完整的任务,既要包含任务本身内容,也要 包含任务执行时间.
2024-04-18 23:11:49
710
4
原创 文件内容操作
但文件描述符表(相当于一个顺序表),里面的长度是固定的,存在上限,不能自动扩容,如果一直打开文件,而不关闭,就会使这个文件描述符表被占满,一旦占满之后,再次尝试打开,就会打开文件失败(其他的操作,网络通信相关的操作,也可能会收到影响).read在读取汉字的时候,能够识别此时采用的是utf-8的编码方式,所以读的时候,读的就是三个字节,但返回成一个char的时候,把utf-8的编码方式,转成了unicode,在unicode中,一个汉字就是2个字节.
2024-04-18 23:10:53
873
1
原创 IO和文件操作
举个栗子:我现在想接100ml的水,可以一次接100ml,也可以接两次,每次接50ml,也可以接10 次,每次接10ml,也可以接100次,每次1ml…对应到针对文件内容操作:比如,要读取100字节的文件数据.可以一次读100个字节,也可以分两次,每次读50字节,还可以分10次,每次读10字节,还可以分100次,每次读1字节…读文件的方式非常灵活,和接水非常类似,因此就称为"文件流"流分成两组:字节流:以字节为单位,读写数据的.读写二进制文件,使用字节流。
2024-04-16 17:15:32
609
3
原创 多线程使用哈希表
HashMap:线程不安全,key允许为nullHashtable :线程安全,使用synchronized 锁Hashtable对象,效率较低,key不允许为nullConcurrentHashMap:线程安全,使用synchronized 锁每个链表头结点,锁冲突降低,充分利用CAS机制,优化了扩容方法,key不允许为null.
2024-04-16 15:43:17
761
1
原创 震惊!!!原来CAS这样理解更简单!!
compare and swap :比较和交换CAS是一条CPU指令(原子性),但可以完成比较和交换操作.CAS的流程,可以想象成一个方法.CAS的伪代码:上图所说的"交换",实际上更多的是用来"赋值";一般更关心内存中,交换后的数据,而不关心reg2寄存器 里交换后的数据.近似的可以认为上述伪代码就是如果address内存地址的值和reg1 寄存器里的值相等,就把reg2寄存器的值赋值给address内存地址.
2024-04-15 08:42:56
873
4
原创 深入理解synchronized
偏向锁:首次使用synchronizd对对象进行加锁的时候,并不是真的加锁,而只是做一个"标记"(非常轻量,非常快,几乎没有开销),如果后面没有其他线程尝试对这个对象加锁,就可以保持这个状态,一直到解锁,(解锁也就是修改一下上述标记,也几乎没有开销),但是,如果在偏向锁的状态下,有某个线程也尝试对这个锁对象进行加锁,立刻就把偏向锁升级成轻量锁(真的加锁了,真的有互斥了).上述锁升级过程,针对一个锁对象来说,是不可逆的,只能升级,不能降级,一旦升级到了重量级锁,就不会回退到轻量级锁(当前JVM的做法).
2024-04-15 08:40:58
914
1
原创 多线程小问题
sleep被调用后当前线程进入TIMED_WAIT状态,不涉及锁相关的操作;start调用方法后, start方法内部会调用Java 本地方法(封装了对系统底层的调用)真正的启动线程,并执行run方法中的代码,run 方法执行完成后线程进入销毁阶段。wait必须在synchronized修饰的代码块或方法中使用,sleep方法可以在任何位置使用;wait是Object类中的一个方法,sleep是Thread类中的一个方法;run方法是一个类中的普通方法,主动调用和调用普通方法一样,会顺序执行一次;
2024-04-12 23:07:27
318
2
原创 synchronized的优化策略
首次使用synchronized对对象进行加锁的时候,不是真的加锁,而只是做一个"标记"(非常轻量,几乎没有开销),如果没有别的线程尝试对这个对象加锁,就可以保持这个状态,一直到解锁(解锁也就是修改一个上述标记,也几乎没有开销).本质上,偏向锁策略就是"懒"字具体体现,能不加锁,就不加锁,能晚加锁,就晚加锁,在很多时候能够把加锁的开销给省下.锁的粒度:指的是:加锁的范围内,包含多少代码,包含的代码越多,锁的粒度就越粗,反之,锁的粒度就越细.有一天,领导给你安排了三个工作,你做完了,要给领导汇报工作.
2024-04-12 23:01:44
393
1
原创 震惊,线程池参数讲的这么明白!!!!
如果当前添加的任务比较少,4个线程就足以能够处理,就只有4个线程在工作了,如果添加的任务比较多,4个线程处理不过来了(有很多线程在排队等待执行),这个过程,线程池就会自动创建出新的线程,来支撑更多的任务.(但创建出来的线程总数,不能超过最大线程数).由于代码大部分都是在等待,那么瓶颈就不在CPU上,每个线程只消耗CPU一点点,更多考虑的是其他方面(比如网络程序,要考虑网卡带宽的瓶颈(比如网卡是1Gbps,一个线程读写速率是100Mbps,最多搞10个线程))这种程序一跑,就能立即吃满一个CPU核心.
2024-04-11 23:52:28
1027
原创 线程池的模拟实现
(2)submit的时候,先判定当前任务队列是否已经比较多了,(自行设定一个阈值)(3)如果确实比较多了,根据刚才构造时指定的拒绝策略,执行不同的逻辑。就需要引入更多的数据结构了,也需要引入"定时器"的概念.(1)构造方法里面提供参数.用参数来表示哪种拒绝策略.b)直接在submit中调用Runnable的run。c)删除队列的队首元素(可以删多个,也可以删一个)(2)有任务队列(使用Runnab即可)实现拒绝策略的核心,在submit这里.d)丢弃当前元素,不添加到队列中.(3)提供submit方法。
2024-04-11 23:51:48
436
原创 震惊!!!原来线程的状态这么简单???
Thread对象已经有了,但还没调用start()方法,系统内部的线程还未创建.就绪状态:RUNNABLE.指的是这个线程"随叫随到",有两种情况.(2)这个线程虽然没在CPU上执行,但可以随时调度到CPU上执行.线程已经终止了,内核中的线程已经销毁了,Thread对象还在.(1)这个线程正在CPU上执行.进行锁竞争的时候产生的等待.因死等进入的阻塞状态.带有超时时间的等待.
2024-04-10 16:28:06
496
4
原创 Thread类的基本用法
创建Thread 实例本质上是创建了一个线程对象,但线程并没有开始运行,创建线程对象仅是为了在之后可以启动一个线程.线程的启动是通过调用start方法来实现的.只有在start()方法被调用之后,线程才会开始执行,当系统调度到这个线程后,才会执行run()方法.t线程正在执行,其他线程都只能提醒一下,t是不是要终止了,t收到这样的提醒之后,还是看看代码是如何写的.终止线程,在Java中,都只是"提醒,建议",真正要不要终止,还得是线程本体代码来决定的!1:创建一个Thread的子类,(叫什么名字不知道)
2024-04-10 16:27:43
353
原创 震惊!!!原来这就是单例模式!!!
单例模式是一种典型的设计模式.设计模式就是为解决编程中的一些典型问题,提供的一些解决方案.遇到这个情景,遇到这个问题,代码应该怎么写,效率更高,能够更好的解决这个问题.在进程中的某个类,有且只有一个对象(不能new出来对个对象),这样的对象,就称为"单例".但如何保证一个类只有一个实例???此时就需要通过一些编程上的技巧,使编译器能够自动发现代码中是否有多个实例,并且在尝试创建多个实例的时候,直接编译出错.从代码上保证单例,这种代码就称为单例模式。
2024-04-04 19:07:37
864
8
原创 震惊!!原来阻塞队列&&消息队列这样理解会更简单!!!
正常情况下,A收到一个客户端请求,就同样请求一次B,A收到的请求多了,B的请求也就会增多,但由于A做的工作比较简单,消耗的资源比较少,B做的工作复杂,消耗的资源比较多,一旦请求量大了,B服务器就容易崩(服务器每次处理一个请求,都会消耗一定的系统资源,如果同一时刻,要处理的请求太多,消耗的总资源数目超出机器能提供的上限,机器可能就会卡死).即使上图:检查心脏的人,排在第二位,但医生没有喊"检查心脏的患者,那检查心脏的患者"只能继续等待,而检查肾,做产检的患者,按照顺序看医生.2:能够让程序"削峰填谷"
2024-04-04 19:06:45
521
1
原创 内存可见性
同时,JVM发现每次load执行的结果,是一样的(t2线程修改之前),因此,**JVM就把上述load操作优化掉了,只是第一次真正进行load,后续再执行到load,而是直接读取已经load过的寄存器中的值了(读取寄存器的速度远远大于 读取内存的速度).**当t2线程修改count的值,但由于t1线程并没有从内存中重新读取,所以获取不到更新后的值.然而,一个load指令消耗的时间,会比一个cmp指令消耗的时间多得多,执行一次load的时间,等于上万次cmp执行消耗的时间.
2024-03-31 15:41:27
430
10
原创 线程的等待通知机制
假设有3个滑稽,1号滑稽在ATM中取钱,2,3号滑稽只能在门口阻塞等待,1号滑稽发现ATM中没钱了,就从ATM中出来了,在2号滑稽进去之前,1号滑稽又进去了,2号又只能阻塞等待,1号发现仍然没钱,又出来了,然后再2号进去之前,1号 又进去了,就这样,1号进进出出,其他滑稽只能阻塞等待.因为t1 ,t2执行抢占式执行,执行顺序不确定,那么就有可能t2先执行了notify,此时t1还没wait,那么notify就不会有任何效果(也不会抛异常),但是后续t1进入wait()之后,就没有人能够唤醒了.
2024-03-31 15:40:15
921
2
原创 线程安全(二)--死锁
);上述代码:thread一共加了两次锁,第一次加锁,肯定是能够成功的,但当第二次加锁的时候,此时,第一次加锁后,还未进行解锁操作,那么第二次加锁操作就不能获得锁对象,就会加锁失败,那么该线程就会进入阻塞等待,等待到第一次加锁 操作完了,释放锁操作,但第一次的操作要释放锁,那么必须执行完第二次加锁,解锁操作(代码顺序执行).
2024-03-30 21:39:39
1214
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人