0.Tcp报文帧格式
- 源端口:发送端的端口号
- 目的端口:接收端的端口号
- 序号(seq):比如一个数据包的序号为301,携带的数据长度有100个字节,那么最后一个字节序号就是400,那么下一个数据包开始的序号就是401
- 确认号(ack):期望收到对方的下一个报文段的数据的第一个字节序号。
A-->B:发过来的数据包,序号(seq)为501,数据长度为200(501~700)
B-->A:这个确认号(ACK)就是701,代表B期望收到A发送的下一个数据序号是701
总之:确认号 = N,代表成功收到了N-1个数据包。
- 数据偏移:??
- URG:表示此报文为紧急传输数据,比如在ftp下包的时候,用户点了取消(CTRL + c),那么这个包不用继续传了,所以这里需要置位。
- ACK:确认位,TCP规定,建立连接后的所有传输报文都需要把ACK置1
- PSH:当两个进程交互的时候,需要一些报文希望对方可以立刻响应,这种情况接收端收到了这个报文就会尽快处理。
- RST:当tcp连接出现严重错误,需要断开连接,RST会置1.
- SYN:再建立连接的时候同步序号。
tcp三次握手建立连接的时候SYN == 1
A-->B发送连接请求:SYN = 1,ACK =0代表请求连接。
B-->A发送响应报文:SYN = 1,ACK =1表示同意连接。
- 终止FIN:用来释放连接,当FIN = 1,表明发送方请求断开连接。
tcp的4次回收断开连接
- 窗口:这个是接收方向发送方要求,发送端的窗口大小。是在动态变化的。
比如A-->B发送了“确认号701,窗口1000”的报文,即A告诉B:B发送接下来报文需要考虑到:我还能收1000个字节的数据。
- 校验和:看前面的数据对不对
- 紧急指针:在URG=1的时候才有意义,紧急指针指出了紧急数据的末尾在报文段中的位置。
- 选项:长度可变,最长可达40字节。
1. 面向连接
- ?client-->server: SYN = 1(连接报文) ,seq = x (这是client发出的第X个包)
- server-->client:SYN=1(连接报文),ack= x+1(server收到了client的第X个包,Sever期待client发的下一个包是X + 1)? ,seq = Y(这是server发出的第Y个包),ACK = 1规定。
- client-->server:ack?= Y+1 (client收到了server的第X个包,client期待Sever发的下一个包是X + 1) seq = x+1?。ACK=1规定。
?(1) client-->server:
- FIN = 1请求断开连接
- seq = u 客户端发的第u个报文
(2)server-->client:
- ACK = 1规定
- seq = v?
- ack = u+1 (收到了client的第u条报文,期望收到u+1的报文)
?(3) server-->client:
- FIN = 1请求断开连接
- ACK = 1
- ack = u+1 (收到了client的第u条报文,期望收到u+1的报文)
- seq = w
(4)client-->server:
- ACK = 1规定
- seq = u+1
- ack = w+1
2.可靠传输原理
- 因为数据链路层的MTU有限制(就算1500),然后向上限制了应用层,传输层,网络层的报文大小。比如在应用层发了一个3000大小的数据帧,到了网络层,就需要对这个数据帧分包,于是把要传输的每一个数据单元称作“分组”。
- 停止等待:就是每发一个分组,就停止发送,等待对方的确认,收到确认报文后,再发下一个分组。
- 超时重传:当主机A发送给主机B一个数据包,A会有一个超时时间(通过超时计时器实现),当大于这个时间主机A没有收到主机B反馈的确认报文,A就会重传这个数据包。
停止等待协议已经可以满足可靠传输了,但有一个致命缺点:效率太低。发送方发送一个数据包之后便进入等待,这个期间并没有干任何事,浪费了资源。解决的方法是:连续发送数据包。
- 自动重传请求ARQ:发送消息的模型如下,?但是这样也不行,万一包过大,一下发完了,缓冲区肯定受不了,所以需要对发送的数据包的量做控制,这叫做TCP的流量控制:具体实现手段就是滑动窗口。
- 滑动窗口:如下图:发送端缓冲区一共有8个数据包,滑动窗口为4。
- 发送端滑动窗口为4,发送0,1,2,3四个数据包
- 接收端回复0,1的接受肯定响应。发送端收到。发送端的发送窗口后移两个。
- 发送端这个时候可发送4,5。
按照上述的流程即可通过滑动窗口发送报文。但这样还是存在问题,过多的来自接收端的确认响应,为了提高效率,可用累计确认的方法。接收端不用收到每个数据包都回复,可累计收到几个包之后在回复一个响应报文。比如接收到收到了0,1,2,3后,回复给发送端一个3就可代表收到了0,1,2,3?
但这样也会带来新的问题:丢包了咋整,比如发送端发了0 1 2 3,接收端收到了0 1 3,按照之前的逻辑,需要重传2,3 但是3是没必要重传的,所以就有了选择确认SACK位(用4个指针确认需要重传的字节流窗口)。
- 通过ARQ协议,用发送-确认回复模式来保证数据包的可靠传输
- 给字节编号:来确认每个包是重传,还是新的数据包
- 超时重传
- 滑动窗口实现流量控制
- 累计确认+选择确认来提高回复与重传的效率
2.拥塞控制
拥塞控制的重点有4个:慢开始、快恢复、快重传、拥塞避免。
塞控制的解决方法是流量控制,流量控制的实现是滑动窗口
Y轴表示的是发送方窗口大小,X轴表示的是发送的轮次(不是字节编号)。
- 简单的说就是不断地调整的调整滑动窗口的大小,来达到对网络的最大效率使用。
3. tcp调用send/recv之后发生了什么?
摘自:深入理解tcp网络编程中的send和recv_hycxag的博客-CSDN博客_sendrecv什么意思
- send返回之时,数据不一定会发送到对端去、,send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer(tcp缓存)中。
- 对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。
- 每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。
参考:掌握这28张图,面试再也不怕被问TCP知识了_一口Linux的博客-CSDN博客
|