Java网络TCP/IP

   正所谓逃得过初一逃不过十五,该来的终究会来,这章就尽我所能的细说TCP吧。行不行呀?细狗! 

   IP基础:

  1. IP(网络层)与MAC(数据链路层)区别:IP地址是主机间通信,源主机定位到目标主机,MAC地址是两设备间直连传输,两点传输。IP目标是终点,MAC目标可能为中转站。
  2. IP分类:优点是快速找到网络和主机地址;缺点是内网无层次,不好与现实网络匹配。
  3. CIDR:解决与现实网络匹配问题,如10.10.10.2/24为前24位网络号-后8位主机号。还可用子网掩码划分网络号和主机号。划分网络为了判断在同一网址下。
  4. 私有IP是内网地址,区域内维护; 公有IP是外网地址,互联网维护且保持地址唯一。
  5. IP分片传输,丢1片则全部废掉。而TCP以(协商得到)MSS长,支持分片传输。
  6. DNS域名解析:句点分割层级,最右层级最高,层级关系如树形结构。

Ping底层(测试连接的命令):

  1. ping基于IP层的ICMP协议(互联网控制报文协议):功能是确认IP包已发送目的地、IP包未到目标地则报告废弃IP包的原因、改善网络设置。
  2. ICMP新增字段:标识符来区分谁发的包,如PID; 序号为每请求1次加1,判断是否丢失包。因为IP包不具有重发机制,所有利用ICMP报获取错误信息再判断处理。
  3. 回送信息:用于判断主机间或路由器间通信所发送的包是否到达目标端,ping命令利用此实现。向目标端发送后接收不同类型回传请求作为判断依据:
  1. 类型8:回传请求。
  2. 类型0:接收目标端应答。
  3. 类型3代号0:目标不可达,因网络不可达。
  4. 类型3代号1:目标不可达,因主机不可达(路由表中无主机记录等)。
  5. 类型3代号2:目标不可达,因协议不可达(防火墙拦截)。
  6. 类型3代号3:目标不可达,因端口不可达(防火墙拦截)。
  7. 类型3代号4:目标不可达,因需要分片的包但无法设置造成不可达。
  8. 类型4:原点抑制信息,包传输间距增大,缓解了网络拥堵,但可能使通信不公平。
  9. 类型5:重定向信息,若发送路径不是最优,则会发送最合适的路由信息和源数据。
  10. 类型11:超时信息,包的生命周期在经过1次路由器后减1,为0时丢弃包,发送超时信息时要设置IP包生命周期(TTL)防循环发送。
  1. ping发送/接收流程: 输入ping命令、源主机构建ICMP回送请求信息(含类型号和序号)、数据包和地址交给IP层(数据包地址为目标地址同时本机IP为源地址)再添加信息构建为IP数据包、加入MAC头(通过ARP协议找MAC地址)、目标路由检查包MAC地址与本机MAC地址(符合接收/不符合丢弃)、接收的目标主机构建回送应答包、源主机接收(若未收到即目标机不可达)。
  2. 若跨网段涉及网关转发、路由转发,则流程新增:在目标主机IP层时,据IP决定路由下次跳转的目标,更换MAC地址,再发送(可能还会跳转或到达目标)。
  3. traceroute应用:命令为tracert(充分利用ICMP差错报文类型),据此有2个作用:
  1. 设置TTL追踪到达目标机所经过的路由器:用UDP发送设置TTL值顺序递增的连续包,每过1个路由生命周期减1,这样下一个包总是比上一个包多经过1个路由,再强制源主机接收ICMP报,往复操作,获得所经过的路由器。
  2. 设置不分片来获取路径MTU:以太网数据链路MTU=1500字节,非以太和路由MTU未知,因此控制发包大小得到ICMP报来找到最佳MTU。源主机发包,设置包不可分片,路由将过大数据包丢弃,返回ICMP报(类型3代号4),适当减小包,再尝试发送。

TCP传输:

  1. TCP/UDP:TCP先建连接再传/UDP立刻传输、TCP可靠/UDP不可靠、TCP控制流量/UDP不控制但传输快、TCP头部长度可变/UDP头长固定8字节。
  2. TCP传输:重传机制、滑动窗口、流量控制、拥塞控制、三握四挥。
  3. UDP传输:不保证数据包可靠交付、不能处理网络拥塞等异常、但传输快,适合广播。
  4. TCP重传机制(联合使用):超时重传、快速重传、SACK、D-SACK:
  1. RTO(超时时间)、RTT(往返时间-发送到接收所耗时间),RTO过大/过小均有问题。
  2. RTO过大:重发慢、效率低、性能差、丢失包较长时间后才重发。
  3. RTO过小:重发快、未确定是包丢失还是包未传输完就执行重发、造成网络拥塞。
  4. RTO应略大于包返回的RTT值,精确的RTO使重传机制更高效。
  5. RTO应动态变化,因为网络时常变化,(根据变化的RTT)计算得到平滑值。
  6. 超时重传:设定时间,因(丢包/丢失应答)超时未收到应答,重发该数据包。TCP重传策略是超时后间隔加倍,即首次重传后,二次重传需间隔首次的2倍时间,超时周期可能较长,则有快速重传策略。
  7. 快速重传:数据引发,发多个数据包时,连续回复3次重复ACK,即已丢包则重传。在发送多个包时,其中一个丢失,后面都会重复前一个包成功的应答,但这样只知道第一个丢包的位置,不知道后面是否丢包。 如发送包1,2,3,4,接收端应答1,2,2...则证明丢了包3(也可能3,4),重传无需等待超时时间,解决了超时周期长的问题,但不确定重传3还是3,4, 则有SACK策略。
  8. SACK:在TCP头上加SACK字段,将缓存表给源发送主机端,则知道了具体丢的包,只发丢失的包即可(需要发送与接收双方都支持SACK)。但SACK无法区分是丢失了包还是丢失了应答,若是丢失应答可能会重复发包。则有D-SACK策略。
  9. D-SACK:用SACK机制通知发送端哪些信息已被重复接收,避免发送端因网络延迟或应答丢失导致未收到回应而去触发重传机制。其优点是可以判断丢包还是丢ACK、是否发送端网络延迟、是否发包被覆盖等。
  1. TCP滑动窗口:窗口(不用等待应答每次可存发送包的最大数)是操作系统开辟的缓存空间,窗口大小由接收端的处理能力确定。在前1个包应答返回前,继续发数据会存入缓存,占满总可接收容量后不可再发送。需要等待有应答完成后,总可接收容量右移一个窗口单位,才可再接收发送的包。应答方式是累计应答,即发送(窗口单位个数的)包,收到最后的1个ACK则代表之前都已成功应答。
  1. 发送端滑动窗口4部分:已发已应答、已发未应答、未发可处理、未使用的空间;总可接收容量=已发送未应答+未发送可处理、 窗口=未发送可处理。

         

  1. 当接收应答后,总可接收容量不变,但向右移动1个窗口单位,如图变化:

          

  1. 接收端滑动窗口3部分:已接收并应答空间、未接收但可接收、未接收不可接收。

         

 

  1. 总可接收容量=窗口=未接收但可接收空间,窗口据自身处理能力决定右移多少。
  2. 发送端滑动窗口约等于接收滑动窗口:例如接收方读取较快,窗口的新容量值通过TCP报字段通知发送端,可能延迟,且发送端窗口还受拥塞控制,顾2者约等。
  1. 流量控制:据接收端处理能力控制发送端窗口,防止不断发包会触发重传、浪费流量。控制流程:例如发送端发送80字节个包,接收端缓存80,但因处理繁忙只读了20,剩60在缓存中,接收端窗口缩容为当前接收窗口值-60,并通知发送端变化,往复如此,为0时关闭窗口。(实际上不是立即关闭,发送端会定时发送窗口探测报文)
  1. 窗口关闭危险:发送窗口为0时关闭,接收窗口>0时通知发送端,若此应答丢失会造成相互等待。解决方式:TCP在窗口为0时,会启动计时器,超时后会发送窗口探测报(含自端窗口值)。若接收端窗口仍为0刷新计时器再重复,不为0打破死锁,(共发3次探测,每次间隔翻倍,3次为0,则发RST中断连接)
  1. 糊涂窗口综合征:接收端繁忙,读取数据少,使发送端窗口越来越小,发的数据太少。
  1. 接收端是小窗口时不通知发送端变化,避免发送端发送小数据。当接收窗口<(MSS , 一半缓存)中的最小值时,设窗口大小为0。反之,大于2者最小值则可用。
  2. 发送端避免发小数据:使用Nagle算法,满足1个条件就发送,都不满足则囤积数据。发送窗口大小>=MSS或者发送数据大小>=MSS时则发送、收到之前全部ACK应答报并且已没有ACK报时则发送。
  1. TCP拥塞控制:流量控制仅控制发送端/接收端,而网络整体间通信也可能造成网络拥塞、丢包、重传等。
  1. 拥塞控制避免发送端的数据填满整个网络,为此设置可调节发送量的拥塞窗口。
  2. 拥塞窗口:发送端维护一个状态量,根据网络拥塞程度动态变化状态量。引入拥塞窗口后,发送端窗口=(接收端窗口,拥塞窗口)2者中的最小值(直等于)。
  3. 拥塞窗口变化规则:网络中无拥塞则增大窗口、网络中有拥塞则减小窗口。
  4. 发送端在一定时间内没有收到应答,就会发生超时重传,可能造成网络拥塞。
  5. 拥塞控制的算法:慢启动、拥塞发生、快速恢复、拥塞避免。
  6. 慢启动:逐步增大发送数据量,发送端每收1个ACK应答,拥塞窗口扩大1。当增大到慢启动门限状态值时,换为拥塞避免算法。
  7. 拥塞发生:超时重传时,慢启动门限=(拥塞窗口的一半),并重置拥塞窗口=1。 快速重传时,拥塞窗口先减半,慢启动门限=拥塞窗口,再进入快速恢复。
  8. 快速恢复:拥塞窗口=慢启动门限+已收到包的数量,重传丢失的数据包,                        若ACK重复则拥塞窗口+1,当收到新的ACK时则拥塞窗口=慢启动门限。换为拥塞避免算法。
  9. 拥塞避免:每收到1个ACK应答,拥塞窗口增加 (1/拥塞窗口大小)的容量。

TCP三次握手:

  1. TCP连接状态标识(SYN:发起连接、ACK:应答回复、RST:断开连接、FIN:结束连接); 
  2. 连接是接收与发送2端都维护一个状态,每次通信都变更,三次握手状态变化:

      

  1. 发送与接收端的ISN不相同。因为网络中报文可能延迟、复制重发、丢失等,为防止不同连接可能相互影响,所以ISN随机且不同。
  1. ISN(初始序列号)的生成: 用于建立连接后,完成此次连接的初始化。
  2. ISN值不写死为0,防止断网重连后值重置为0。
  3. ISN每4微秒+1,超过2^32后,重置为0。
  4. ISN是递增值,并且会加入随机值,防被猜到。
  1. TCP三次握手作用:初始化并同步序号建立可靠连接、避免历史连接、防止连接浪费。
  1. 同步双方序列号,实现顺序发送接收、去除重复、标识应答。如上图,发送的一方总是将自身isn标识携带发送,应答的一方在此isn上+1,实现连接的可靠建立。
  2. 避免历史连接:因为网络拥塞时有较多的发送端的SYN,可能旧的SYN先于新SYN到达服务端,服务端应答的SYN+ACK,接收的客端能够根据上下文判断是否为新的连接,是旧连接则发送RST中断、新连接则发送ACK建立连接。
  3. 防止连接浪费:服务端收到第3次握手信息才建立连接,否则不建立。若仅2次握手,服务端不知到客户端是否收到第2次握手信息就建立连接。可能是无效连接。
  1. 发送序号SYN用于保证之后可以顺序传输数据,服务端收到SYN发送应答,但若客户端此时挂掉,会阶段性重试,Linux尝试5次重发。
  1. Linux每次重试(如RTO初始值=1s)间隔:1s、2s、4s、8s、16s、32s后断开连接。
  2. SYN泛洪攻击:如上重试共耗时63s,若黑客期间发大量SYN并故意不应答,就会造成SYN队列占满、网络拥塞等问题。
  3. 泛洪攻击仅能缓解:如开启tcp_syncookies功能、减少重试次数、增大SYN队列。
  1. TCP连接队列:第一次握手后服务端收到的信息存储在队列中,此队列称为半连接队列(SYN队列)、 第三次握手后服务端转移半连接队列的信息到新的队列,此新队列称为全连接队列(accept队列)。
  1. SYN队列和accept队列都有最大限制,超过限制Linux默认丢弃新的连接并中断。 
  2. 全连接队列溢出:服务端用ss命令查看accept队列,并可以增大全连接队列容量解决溢出。全连接队列溢出是正常连接的数量大并非恶意攻击。
  3. 半连接队列溢出:即SYN泛洪攻击(DDos)是Dos的一种,仅能缓解此攻击。原理是大量发送第一次握手而不发送第三次握手,使服务端频繁重发造成崩溃。这种攻击因为难以与正常连接请求区分所以很难根治,目前主要解决方法除了增大半连接队列、减少重传次数外就是开启tcp_syncookies功能。
  4. tcp_syncookies功能:据当前状态计算得到私密值,放入服务端的应答中。若客户端第三次握手携带私密值,则建立连接。此过程在第一次握手后不用将信息存入SYN队列中所以能缓解DDoS,但还是无法避免服务端频繁重发。
  1. 第一次握手丢包客户端重传5次、第二次握手丢包客户端重传5次并重置、第三次握手丢包服务端重传5次。
  1. 已建立连接,服务端挂掉,客户端发包时:客户端无应答收到,会默认重传15次,每次间隔RTO(且RTO指数增长),之后断开连接。
  2. 已建立连接,服务端挂掉,客户端不发包时:一定时间过后仍无活动,会启动保活机制,保活超时后断开连接。
  3. 已建立连接,客户端挂掉,服端不主动发包:一定时间过后仍无活动,会启动保活机制,保活超时后断开连接。
  4. 保活机制:一定时间内有活动则刷新计时。若超过此时间后仍无活动,则启动保活机制,即每隔一段时间发探测报。Linux中7200s后无活动则启动保活机制,之后每隔75s发1次探测报,共9次。即7875s后确定1个死亡连接。(参数可调)
  1. TCP与Socket: 成功连接socket用于后续传输、监听socket(主动打开:scoket、connect; 被动打开:scoket、bind、listen)

  

 

  TCP四次挥手:

  1. 因为TCP也是全双工协议,双方都要关闭,需要每一方向对方发FIN和ACK。

      

  1. 四次挥手状态:客户端是主动关闭端、服务端是被动关闭端,(有双主动关闭)
  2. TCP不一定四次挥手:在第2次挥手和第3次挥手间close_wait状态主要是等待服务端在关闭连接前要发送的数据,若服务端在此期间无数据发送可以合并这两次挥手变为Fin+Ack。
  3. TIME_WAIT状态:等待2MSL时间后关闭,MSL(报文最长生存时间)。Linux中MSL=30s。
  1. 等待2MSL:避免服端未收到最后的ACK,客端就已关闭。
  2. 等待2MSL:网络中可能有的包延迟了,等待2MSL足够两端旧的包都消失,保证再有包即新连接。也避免新连接可能被旧连接残留数据干扰。
  3. 等待2MSL存在问题:若服务端主动关闭等待2MSL,会占用资源。应由客户端主动关闭等待2MSL,这样只是占用端口,端口被占用完概率低。
  4. 优化:(客户端主动关闭)复用处于等待的socket、或使用时间戳、直接关闭等。
  1. 第一次挥手丢FIN则客户端重传、第二次挥手丢ACK则客户端重传FIN、第三次挥手丢FIN则服务端重传、第四次挥手丢ACK则服务端重传FIN。重传超过上限,发RST报。
  1. 若调shutdown()关闭,可设置关闭发送或关闭接收。未收到第三次FIN时,可处于等待(接收/发送)状态。
  2. 若调close()关闭,调用端既关闭发送又关闭接收。未收到第三次FIN时,默认等待60s,超时后直接关闭。

TCP优化:

  1. TCP第三次握手可携带数据发送,前二次握手不可携带数据发送。
  2. Http-get请求分3种情况:
  1. 每次传输数据都建立三次握手,之后再传输。每次传输耗时2.5个RTT。
  2. 每次传输数据都建立三次握手并且第3次携带数据,再传输。每次2个RTT。
  3. 开启Fast Open功能:首次传输建立三次握手,且第3次携带数据,之后用cookie维护传输。首次传输耗时2个RTT,之后每次耗时1个RTT。
  4. 将信息维护到cookie中,每次请求携带信息标识,取代每次传输都建立三次握手。
  1. 避免发送小数据 (头部占空间大于数据体的数据):Nagle算法(默认打开)、延迟确认。
  1. Nagele算法(用于客户端):当已收到的全部ACK或包>=MSS时则发送,不满足时则继续囤积收到的ACK或包。Nagle适合交互少的场景,交互强的场景需要关闭。
  2. 延迟确认(用于服务端): 当发送包时,前1个应答ACK随之一起发送。当不发送包时,前1个应答ACK延迟等待,若等到了数据包就随之一起发生,若等到的是新的ACK则立即发送这个旧的ACK。
  3. Nagle算法与延迟确认混合使用,则会增加传输耗时,需要关闭其中1种。
  1. 三次握手优化:减少重传次数、增大Syn队列/Accept队列、开启tcp_syncookies。
  2. 四次挥手优化:主动关闭(close关闭则不发且不收、shutdown关闭则不发或不收)。
  1. 设置TIME_WAIT状态下的连接最大上限:超过上限,后续连接不进入TIME_WAIT,直接关闭。降低耗时。
  2. 开启时间戳:主动关闭的一端复用处于TIME_WAIT等待的socket。降低耗时。
  3. 设置调用close()的最大连接上限:超过上限,后续连接直接RST强制关闭。
  4. 当被动关闭端没有要发送的数据时,调用close(),使第2、第3次挥手合并发送。
  5. 双主动关闭:

                     

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值