目录

1.协议端格式

1.UCP

2.TCP

2.Tcp的核心机制

2.1确认应答

2.2超时重传

2.3连接管理

1.如何建立连接(双方是否能进行通信的验证)

2.如何断开连接

2.4滑动窗口

2.5流量控制

2.6阻塞控制

2.7延迟应答

2.8捎带应答

2.9面向字节流-->黏包问题

2.10Tcp异常处理


1.协议端格式

1.UCP

应用层报文解析 java 应用层报文长度_网络

 

以UDP客户端为例:

源端口:操作系统给客户端分配的端口

目的端口:服务器的端口

报文长度:2字节,范围0-65535-->64k,可能小

校验和:验证网络传输的数据是否正确,网络上传输数据本质是电信号和光信号,外界干扰,会导致错误,校验和能发现错误,不能保证一定正确,但校验和不正确,数据一定不正确

2.TCP

应用层报文解析 java 应用层报文长度_服务器_02

 源端口号和目的端口号,校验和和UDP类似

32位序号,32位确认序号:防止出现发送和应答不对应

4位首部长度:4个bit,0-15表示TCP报头长度,TCP长度是变长的,此处是4字节

保留位:现在不用,可能以后会用

2.Tcp的核心机制

可靠传入:最核心

2.1确认应答

关键是接收方收到消息之后,给发送方,返回一个应答报文,表示自己已经收到了

问题:网络传输可能后发先至,如果是多条信息,可能出现问题(发送和回答可能没有对应)

方法:添加序号和确认序号

应用层报文解析 java 应用层报文长度_重传_03

 发送数据1-1000,意思是TCP报头的序号是1,报文长度是1000

2.2超时重传

对确认应答进行补充(如果丢包,确认应答可能会有问题)

发送数据丢了和返回的ACK丢了,发送方分辨不了,给一点反应时间,还没有收到ACK,就重传,一般连续两次丢了概率较低

应用层报文解析 java 应用层报文长度_网络协议_04

 

 超时重传,重传数据成功不是100%

2.3连接管理

1.如何建立连接(双方是否能进行通信的验证)

三次握手:客户端和服务器之间,通过三次交互,建立连接的剁成

应用层报文解析 java 应用层报文长度_服务器_05

 

应用层报文解析 java 应用层报文长度_重传_06

 

如果第二位ACK为1,表示这个报文是一个"确认报文段"

如果第五位SYN为1,是同步报文段-->主机A和主机B之间要建立连接

双方彼此知道和对方建立连接

中间两次合二为一,封装两次不如封装一次更高效,中间两次能合并,因为B发送ACK,B发送SYN发送时机相同(B给A发送的是操作系统内核进行的)

应用层报文解析 java 应用层报文长度_网络协议_07

 如果A的发送或者B的发送出现问题,A没有接收到回应,重传,重传还没有回应就放弃

2.如何断开连接

四次挥手

三次握手后,建立连接后,操作系统内核中,要使用一定的数据结构来保存连接信息,保存的信息时五元组,双方都要保存.,保存信息要占用系统资源,有一天,连接断开,之前的连接信息就可以释放.

应用层报文解析 java 应用层报文长度_服务器_08

 

双方给对方发送了FIN(结束报文段)请求,给对方一个ACK确认报文

四次挥手,可能是客户端主动发起,也可能是服务器主动发起

四次挥手,中间两次大概率合并不了

不能合并的原因,B发送ACK,B发送FIN发送时机不同,B发送ACK是内核负责和B发送的FIN是用户代码负责(B中代码调用socket.colse()方法,才会触发FIN)

收到FIN,立即由内核返回ACK,FIN是执行到用户代码中的close才会触发,取决于用户怎么写,

如果间隔时间短可能一起发送,如果间隔时间长,就要两次发送.

CLOSE_WAIT:挥了两次的状态,等待代码中调用close()方法,来进行后序的挥手,正常情况,一个服务器不存在大量的CLOSE_WAIT,如果存在,说明是代码bug,close没有执行到

TIME_WAIT:谁主动发起,谁进入TIME_WAIT,给最后一次ACK提供重传的关系,此时A 本来应该销毁连接,释放资源,但是会在TIME_WAIT状态等待一会,防止最后一个ACK丢包(相当于售后),如果B不会在重传FIN之后,在真正销毁.

如果ACK丢了,B不知道是ACK丢了,还是FIN丢了,此时意味着B一会重传FIN,如果A销毁了,B发送的ACK就没有能解决的了

应用层报文解析 java 应用层报文长度_服务器_09

 MSL:表示网络上任意两点之间传输的最大时间

2.4滑动窗口

本质,批量发送数据

一次发送多组数据,一起等,一份等待时间,等待了多份ACK,滑动窗口就缩短等待时间

一次批量发送N个,就是N个窗口,滑动就是不用把四组都等到就发送,而是第一组返回就发送新的

当2001这个ack到达后,就认为1001-2000收到了,就立即发送下一组,直观就像窗口在往下滑

当前窗口你越大,传输速度越快

但也会出现问题:

1.ACK丢了

假设,收到5001时,但没有收到,3001和4001,意味着1-5000都收到了,3001和4001丢包,只要5001收到了,就涵盖了3001和4001

2.数据丢了

例如,1001-2000这个数据丢了,所有B要反复索要1001这个数据,即使A已经给B 往后发了,这个时候仍要索要1001,当索要若干次后,A就会重传,重传后补齐,后续传输过,就不用在重传,B就向A索要从最大序号开始的

2.5流量控制

滑动窗口的延伸,保证可靠性

在滑动窗口中,窗口越大,传输速率越高,发送方太快,接收方处理不过来,就丢包了,发送方还要重传

流量控制的关键就是能衡量接收方处理速度,直接使用接收方接收缓冲区的剩余空间大小来衡量当前的处理能力

接收缓冲区相当于一个阻塞队列,B在调用read方法中,可以从接收缓冲区来取数据

窗口大小为0-->不是完全不发送,不发送数据,会定期发送探测报文,只为触发ACK,知道 当前窗口的大小

2.6阻塞控制

也是滑动窗口的延伸,限制滑动窗口发送的速率

阻塞控制衡量的是发送方到接收方,这整个链路之间拥堵情况(处理能力)

AB中有很多设备,A发送的速度,取决于B的处理能力,也取决于中间链路的处理能力,

方法:通过实验方式,调整发送速度,找到合适的值

A开始以一个比较小的窗口发送,如果数据很流畅,就增大,如果丢包就减小,通过增大/减小就找到了一个范围,拥塞窗口就在这个范围不断变化,达到动态平衡

应用层报文解析 java 应用层报文长度_网络协议_10

 

通过拥塞窗口来制约滑动窗口的大小

最终滑动窗口=min(拥塞窗口,流量控制窗口)

速度接近丢包极限,没真丢

指数增长一定程度就会线性增长.

拥堵的值,取决于是否丢包,丢包就拥堵,然后根据拥堵的值,来更新阈值

2.7延迟应答

相当于流量控制的延伸,在流量控制的基础上,让窗口尽量大

在发送时,会询问剩余空间,方法是不立刻回答,而是少外晚一些回答,意味着这个时间中,可以多出一点水,,在有限条件下,提高了传输速度

2.8捎带应答

延迟应答的延伸

因为延时应答,导致ACK返回时机和应用代码返回响应时机重合,就把ACK和响应数据,合二为一

2.9面向字节流-->黏包问题

TCP接收缓冲区中,若干个应用层数据报混在一起了,分不清谁是谁

方法:在应用层协议中,要加包之间的边界(例如:加;)

2.10Tcp异常处理

1.进程终止:进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别。

2.机器重启:和进程终止的情况相同。

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