网络原理----TCP/IP(3)

发布于:2025-03-04 ⋅ 阅读:(11) ⋅ 点赞:(0)

核心机制七----延时应答

默认情况下,接收方都是在收到数据报的第一时间,就返回ack,但是可以通过延时返回ack的方式来提高效率,理论上不是100%提高效率,但还是有一定帮助的。

因为如果接收数据的主机⽴刻返回ACK应答,这时候返回的窗⼝可能⽐较⼩.

  • 假设接收端缓冲区为1M.⼀次收到了500K的数据;如果⽴刻应答,返回的窗⼝就是500K; 但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了 ,在这种情况下,接收端处理还远没有达到⾃⼰的极限,即使窗⼝再放⼤⼀些,也能处理过来;
  • 如果接收端稍微等⼀会再应答,⽐如等待200ms再应答,那么这个时候返回的窗⼝⼤⼩就是1M; ⼀定要记得,窗⼝越⼤,⽹络吞吐量就越⼤,传输效率就越⾼.我们的⽬标是在保证⽹络不拥塞的情况下 尽量提⾼传输效率;

那么所有的包都可以延迟应答么?肯定也不是;

• 数量限制:每隔N个包就应答⼀次; • 时间限制:超过最⼤延迟时间就应答⼀次; 具体的数量和超时时间,依操作系统不同也有差异;⼀般N取2,超时时间取200ms(这个数值不固定,根据实际情况而定);

核心机制八---捎带应答

在延迟应答的基础上,我们发现,很多情况下,客⼾端服务器在应⽤层也是"⼀发⼀收"的.意味着客⼾端 给服务器说了"How areyou",服务器也会给客⼾端回⼀个"Fine,thank you"; 那么这个时候ACK就可以搭顺⻛⻋,和服务器回应的"Fine,thank you"⼀起回给客⼾端。

引入了延时应答,ack可以往后延时一段时间,恰好这个时候要返回响应数据,此时就可以把ack也代入到响应数据中,一起返回,ack设为1,窗口大小设为接收缓冲区剩余值,确认序号设为合适的值;把两个包合成一个,就能起到提高效率的作用。

核心机制九---面向字节流

创建⼀个TCP的socket,同时在内核中创建⼀个发送缓冲区和⼀个接收缓冲区;

  • 调⽤write时,数据会先写⼊发送缓冲区中; 如果发送的字节数太⻓,会被拆分成多个TCP的数据包发出; 如果发送的字节数太短,就会先在缓冲区⾥等待,等到缓冲区⻓度差不多了,或者其他合适的时机发 送出去;
  •  接收数据的时候,数据也是从⽹卡驱动程序到达内核的接收缓冲区;然后应⽤程序可以调⽤read从接收缓冲区拿数据;
  • 另⼀⽅⾯,TCP的⼀个连接,既有发送缓冲区,也有接收缓冲区,那么对于这⼀个连接,既可以读数据,也可以写数据.
  • 这个概念叫做全双⼯由于缓冲区的存在,TCP程序的读和写不需要⼀⼀匹配,例如:写100个字节数据时,可以调⽤⼀次write写100个字节,也可以调⽤100次write,每次写⼀个字节;读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以⼀次read100个字节,也可以⼀ 次read⼀个字节,重复100次;

在这个过程中会出现粘包问题

1.⾸先要明确,粘包问题中的"包",是指的应⽤层的数据包. 

  •  在TCP的协议头中,没有如同UDP⼀样的"报⽂⻓度"这样的字段,但是有⼀个序号这样的字段.
  •  站在传输层的⻆度,TCP是⼀个⼀个报⽂过来的.按照序号排好序放在缓冲区中.站在应⽤层的⻆度,看到的只是⼀串连续的字节数据. 那么应⽤程序看到了这么⼀连串的字节数据,就不知道从哪个部分开始到哪个部分,是⼀个完整的应 ⽤层数据包.

2. 那么如何避免粘包问题呢?归根结底就是⼀句话,明确两个包之间的边界. 

  • 对于定⻓的包,保证每次都按固定⼤⼩读取即可;例如上⾯的Request结构,是固定⼤⼩的,那么就从 缓冲区从头开始按sizeof(Request)依次读取即可;
  • 对于变⻓的包,可以在包头的位置,约定⼀个包总⻓度的字段,从⽽就知道了包的结束位置; 对于变⻓的包,还可以在包和包之间使⽤明确的分隔符(应⽤层协议,是程序猿⾃⼰来定的,只要保证 分隔符不和正⽂冲突即可);

 3.思考:对于UDP协议来说,是否也存在"粘包问题"呢?

  •  对于UDP,如果还没有上层交付数据,UDP的报⽂⻓度仍然在.同时,UDP是⼀个⼀个把数据交付给应 ⽤层.就有很明确的数据边界.
  • 站在应⽤层的站在应⽤层的⻆度,使⽤UDP的时候,要么收到完整的UDP报⽂,要么不收.不会出 现"半个"的情况.

核心机制十----异常情况的处理

TCP在通信过程中存在特殊情况

1.进程终止:进程终止和主动退出没有本质区别,进程终止会释放⽂件描述符,仍然可以发送FIN,进程虽然没了,但是TCP的连接信息还存在,此时四次挥手还是可以正常进行的。。

2.主机关机:正常流程的关机,本质上还是会先杀死所有的用户进程,与进程终止情况相同。

最终B任然可以把连接释放掉 

3.主机掉电/网线断开:接收端认为连接还在,⼀旦接收端有写⼊操作,接收端发现连接已经不在了,就 会进⾏reset.即使没有写⼊操作,TCP⾃⼰也内置了⼀个保活定时器,会定期询问对⽅是否还在.如果 对⽅不在,也会把连接释放。

主机掉电:

网线断开就是上面两种情况的结合

TCP小结

为什么TCP这么复杂?因为要保证可靠性,同时⼜尽可能的提⾼性能.

  • 可靠性: • 校验和 • 序列号(按序到达)• 确认应答 • 超时重发 • 连接管理 • 流量控制 • 拥塞控制
  • 提⾼性能:• 滑动窗 • 快速重传 • 延迟应答 • 捎带应答
  • 其他: • 定时器(超时重传定时器,保活定时器,TIME_WAIT定时器等)

TCP与UDP的对比

TCP用于可靠传输的情况,应用于文件传输,重要状态更新等场景;UDP用于对⾼速传输和实时性要求较⾼的通信领域,例如,早期的QQ,视频传输等.另外UDP可以⽤ 于⼴播;

如何基于UDP实现可靠运输?往TCP上套

3.网络层

3.1IP协议

基本概念

• 主机:配有IP地址,但是不进⾏路由控制的设备; • 路由器:即配有IP地址,⼜能进⾏路由控制; • 节点:主机和路由器的统称;

协议头格式:

IP协议/网络层做的工作,主要是两个:

1.地址管理,使用IP地址这样的概念,标识网络上的某个设备的位置;

2.路由器选择,在两个通信的节点之间,规划处一个合理的路径。

各部分相关介绍:

  1. 4位版本号(version):指定IP协议的版本,对于IPv4来说,就是4.
  2. 4位首部长度:IP协议的报头,也是变长的选项,IP头部的⻓度是多少个32bit,也就是length*4的字节数.4bit表⽰最 ⼤的数字是15,因此IP头部最⼤⻓度是60字节.
  3. 8位服务类型:决定了IP协议的工作方式,3位优先权字段(已经弃⽤),4位TOS字段,和1位保留字段(必须置为 0).4位TOS分别表⽰:最⼩延时,最⼤吞吐量,最⾼可靠性,最⼩成本.这四者相互冲突,只能选择⼀个. 对于ssh/telnet这样的应⽤程序,最⼩延时⽐较重要;对于ftp这样的程序,最⼤吞吐量⽐较重要.
  4. 16位总长度:IP数据报整体占多少个字节,就是一个IP数据报(报头+载荷)的长度.
  5. 16位标识:拆包,把拆出来的多个包,设为相同的标识;组包,把相同标识的数据包组合到一起.
  6. 3位标志:其中一个标志位表示是否触发了拆包操作,还有一个表示当前包是否是最后一个。
  7. 13位片偏移:描述了先后顺序,偏移小的放前面,大的放后面.
  8. 8位生存时间:数据报到达⽬的地的最⼤报⽂跳数.⼀般是64.每次经过⼀个路 由,TTL-=1,⼀直减到0还没到达,那么就丢弃了.这个字段主要是⽤来防⽌出现路由循环.
  9. 8位协议:标识传输层使用哪种协议,分用的时候,IP协议解析IP数据报的时候,拿到载荷,交给上层处理,此处8位协议号,就能起到区分效果.(传输层到应用层通过端口号区分,网络层到传输层=>8位协议,数据链路层到网络层=>也有一个类似的协议编号)
  10. 16位首部校验和:使⽤CRC进⾏校验,来鉴别头部是否损坏.
  11. 32位源地址和32位⽬标地址:表⽰发送端和接收端,IP协议最关键的部分,IP地址本质上是通过32位的整数来表示的,由于32位 整数不方便阅读,通常会把IP写作点分十进制表示方式,用三个点分成四个部分。如图:.

3.2地址管理

IP不够了该怎么办?

1.动态分配IP:上网再分配,不上网就不分配,有所缓解,不能根本上解决问题.

2.NAT机制,网络地址转换(当前网络世界最主要的方式),把所有的IP分成两个大类

公网IP/外网IP:公网IP是唯一的

私网IP/内网IP:私网IP在不同的局域网中,可以重复。

  • 10.*,前8位是⽹络号,共16,777,216个地址 
  • 172.16.到172.31.,前12位是⽹络号,共1,048,576个地址
  • 192.168.*,前16位是⽹络号,共65,536个地址 包含在这个范围中的,都成为私有IP,其余的则称为全局IP(或公⽹IP);

NAT机制,就可以用一个外网IP对应到一系列的内网的设备,一个设备有一个独立的局域网IP(允许重复),但是多个设备共用同一个外网IP(不允许重复).

NAT背景下网络通信如何进行

1.同一个局域网下,设备A访问设备B,由于IP本身不允许重复,自然不收任何影响,NAT不起到作用.

2.公网设备A访问公网设备B,由于公网IP本身也不重复,也不受到影响,NAT不起作用.

3.不同局域网,设备A访问设备B是不允许的,NAT机制禁止这样的访问方式.

4.局域网设备A访问公网设备B.就是网络地址映射。

相关流程图:

5.公网设备A访问局域网设备A,不允许.

3.IPv6:IPv6并不是IPv4的简单升级版.这是互不相⼲的两个协议,彼此并不兼容;IPv6⽤16字节128位 来表⽰⼀个IP地址;但是⽬前IPv6还没有普及.

IP地址的其他规则

⽹段划分

IP地址分为两个部分:⽹络号和主机号

  ⽹络号:保证相互连接的两个⽹段具有不同的标识;主机号:同⼀⽹段内,主机之间具有相同的⽹络号,但是必须有不同的主机号;

在同一个局域网中,网络号必须相同,主机号必须不同;两个相邻的局域网中,网络号必须不同,主机号无限制。

  •  不同的⼦⽹其实就是把⽹络号相同的主机放到⼀起.
  • 如果在⼦⽹中新增⼀台主机,则这台主机的⽹络号和这个⼦⽹的⽹络号⼀致,但是主机号必须不能和 ⼦⽹中的其他主机重复. 通过合理设置主机号和⽹络号,就可以保证在相互连接的⽹络中,每台主机的IP地址都不相同.

那么问题来了,⼿动管理⼦⽹内的IP,是⼀个相当⿇烦的事情.

 • 有⼀种技术叫做DHCP,能够⾃动的给⼦⽹内新增主机节点分配IP地址,避免了⼿动管理IP的不便. ⼀般的路由器都带有DHCP功能.因此路由器也可以看做⼀个DHCP服务器。

过去曾经提出⼀种划分⽹络号和主机号的⽅案,把所有IP地址分为五类,如下图所⽰:

这个方案,固定分为五类,使用前缀来区分是哪一类,每一个类,网络主机号都是固定的,但随着Internet的⻜速发展,这种划分⽅案的局限性很快显现出来,⼤多数组织都申请B类⽹络地址,导致B 类地址很快就分配完了,⽽A类却浪费了⼤量地址;

针对这种情况提出了新的划分⽅案,称为CIDR(Classless Interdomain Routing):

引⼊⼀个额外的⼦⽹掩码(subnet mask)来区分⽹络号和主机号;⼦⽹掩码也是⼀个32位的正整数.通常⽤⼀串"0"来结尾; 将IP地址和⼦⽹掩码进⾏"按位与"操作,得到的结果就是⽹络号; ⽹络号和主机号的划分与这个IP地址是A类、B类还是C类⽆关;

可⻅,IP地址与⼦⽹掩码做与运算可以得到⽹络号,主机号从全0到全1就是⼦⽹的地址范围;

特殊的IP地址

  •  将IP地址中的主机地址全部设为0,就成为了⽹络号,代表这个局域⽹;
  •  将IP地址中的主机地址全部设为1,就成为了⼴播地址,⽤于给同⼀个链路中相互连接的所有主机发 送数据包;
  •  127.*的IP地址⽤于本机环回(loop back)测试,通常是127.0.0.1。

小结

1.IPv4地址,占几个字节,不够用了(动态分配,NAT,IPv6);

2.IP地址构成:网络号+主机号  子网掩码;

3.特殊的IP:主机号为0,主机号全为1,127开头。

3.3路由选择

通过IP协议进行数据转发的过程,在复杂的⽹络结构中,找出⼀条通往终点的路线;路由的过程,是⼀跳⼀跳"问路"的过程. 所谓"⼀跳"就是数据链路层中的⼀个区间.具体在以太⽹中指从源MAC地址到⽬的MAC地址之间的帧 传输区间.

主要步骤:

IP数据包的传输过程也和问路一样,当数据包到达某个路由器的时候,就会匹配这个这个路由器的“路由表”(路由表记录了这个路由器周围的设备的IP,以及每个设备要通过那个路口转发过去);如果目的IP刚好匹配到了路由表中的记录,直接按照当前的对应的口转发过去就行了;如果没有匹配到,路由表就会有下一个特殊的表项,“下一跳”指向的设备,即上一级路由器所在的位置(这些路由器越往上,涵盖的范围也越大)。