传输层

传输层:负责将数据能够从发送端传输到接收端
主要协议:TCP/UDP
UDP博客


TCP(Transmission Control Protocol):传输控制协议


TCP协议段格式


这里写图片描述


32位序列号:数据包编码

4位TCP报头⻓度: 表⽰该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最⼤⻓度是15 * 4 =60
URG: 紧急指针是否有效
ACK: 确认号是否有效
PSH: 提⽰接收端应⽤程序⽴刻从TCP缓冲区把数据读⾛
RST: 对⽅要求重新建⽴连接; 我们把携带RST标识的称为复位报⽂段
SYN: 请求建⽴连接; 我们把携带SYN标识的称为同步报⽂段
FIN: 通知对⽅, 本端要关闭了, 我们称携带FIN标识的为结束报⽂段

16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP⾸部, 也包含TCP数据部分
16位紧急指针: 标识哪部分数据是紧急数据


TCP连接管理机制


这里写图片描述

这里写图片描述
服务器状态转换:

[CLOSED -> LISTEN] 服务器端调⽤listen后进⼊LISTEN状态, 等待客户端连接;(调用socket,listen)
[LISTEN -> SYN_RCVD] ⼀旦监听到连接请求(同步报⽂段), 就将该连接放⼊内核等待队列中, 并向客户端发送SYN确认报⽂.(半连接队列 默认1024)(SYN攻击
[SYN_RCVD -> ESTABLISHED] 服务端⼀旦收到客户端的确认报⽂, 就进⼊ESTABLISHED状态,可以进⾏读写数据了.(完全连接队列 默认128)
[ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调⽤close), 服务器会收到结束报⽂段,服务器返回确认报⽂段并进⼊CLOSE_WAIT;
[CLOSE_WAIT -> LAST_ACK] 进⼊CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据); 当服务器真正调⽤close关闭连接时, 会向客户端发送FIN, 此时服务器进⼊LAST_ACK状态,等待最后⼀个ACK到来(这个ACK是客户端确认收到了FIN)
[LAST_ACK -> CLOSED] 服务器收到了对FIN的ACK, 彻底关闭连接.

客户端状态转化:

[CLOSED -> SYN_SENT] 客户端调⽤connect, 发送同步报⽂段;
[SYN_SENT -> ESTABLISHED] connect调⽤成功, 则进⼊ESTABLISHED状态, 开始读写数据;
[ESTABLISHED -> FIN_WAIT_1] 客户端主动调⽤close时, 向服务器发送结束报文段, 同时进⼊FIN_WAIT_1;
[FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报⽂段的确认, 则进⼊FIN_WAIT_2, 开始等待服务器的结束报⽂段;
[FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报⽂段, 进⼊TIME_WAIT, 并发出LAST_ACK;
[TIME_WAIT -> CLOSED ] 客户端要等待⼀个2MSL(Max Segment Life, 报⽂最⼤⽣存时间)的时间,才会进⼊CLOSED状态.(MSL默认60S 可配置,通过cat /proc/sys/net/ipv4/tcp_fin_timeout命令可查看)


TIME_WAIT等待2MSL原因:因为防止最后一条ACK丢失,如果丢失,对方在1MSL时间内等不到ACK,认为上次FIN请求丢失,还会重发一条FIN(TCP重传机制),当等待2MSL后其实就是在等待看是否还有FIN。如果没有确认断开完成,最后一次发送的ACK对方收到。


  1. 服务器有大量的CLOSE_WAIT状态,是什么原因?

服务器bug,忘记关闭文件描述符。

  1. 服务器有大量的TIME_WAIT,导致大量端口号被占用,怎么办?

重用端口号,通过setsockopt()设置了缓冲区大小。端口号重用


为什么TCP是可靠传输?


1 . 确认应答(ACK)机制

这里写图片描述


2 . 超时重传机制

主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据⽆法到达主机B;
如果主机A在⼀个特定时间间隔内没有收到B发来的确认应答, 就会进⾏重发

由于超时重传机制主机B会收到很多重复数据. 那么TCP协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉,这时候我们可以利⽤前⾯提到的序列号以及TCP接收缓冲区删除重复的包。

悲观
Linux中(BSD Unix和Windows也是如此), 超时以500ms为⼀个单位进⾏控制, 每次判定超时重发的超时时间都是500ms的整数倍.
如果重发⼀次之后, 仍然得不到应答, 等待 2500ms 后再进⾏重传.
如果仍然得不到应答, 等待 4
500ms 进⾏重传. 依次类推, 以指数形式递增.
累计到⼀定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接


3 . 滑动窗口

窗口大小:⽆需等待确认应答⽽可以继续发送数据的最⼤值

操作系统内核为了维护滑动窗⼝, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉;
窗⼝越⼤, 则网络的吞吐率就越⾼

滑动窗口下的丢包重传:
a . 数据包已经抵达, ACK被丢了

部分ACK, 可以通过后续的ACK进⾏确认

b . 数据包丢了
这里写图片描述


4 . 流量控制
接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继⽽引起丢包重传等等⼀系列连锁反应.因此TCP⽀持根据接收端的处理能⼒, 来决定发送端的发送速度. 这个机制就叫做流量控制。

1 .接收端将⾃⼰可以接收的缓冲区⼤⼩放⼊ TCP ⾸部中的 “窗⼝⼤⼩” 字段, 通过ACK端通知发送端;
2 .窗⼝⼤⼩字段越⼤, 说明网络的吞吐量越⾼;
3 .接收端⼀旦发现⾃⼰的缓冲区快满了, 就会将窗⼝⼤⼩设置成⼀个更⼩的值通知给发送端;
4 .发送端接受到这个窗⼝之后, 就会减慢⾃⼰的发送速度;
5 .如果接收端缓冲区满了, 就会将窗⼝置为0; 这时发送⽅不再发送数据, 但是需要定期发送⼀个窗⼝探测数据段, 使接收端把窗⼝⼤⼩告诉发送端(16位窗⼝大小,TCP⾸部40字节选项中还包含了⼀个窗⼝扩⼤因⼦M, 实际窗⼝⼤⼩是 窗⼝大小的值左移 M 位)

这里写图片描述


5 . 拥塞控制
(慢启动)先发少量的数据, 了解当前的网络拥堵状态, 再决定按照多⼤的速度传输数据。

拥塞窗口(cwnd):
发送开始的时候, 定义拥塞窗⼝⼤⼩为1;(不超过慢启动阈值< ssthresh >时,以指数增加)
每次收到⼀个ACK应答, 拥塞窗⼝加1;
每次发送数据包的时候, 将拥塞窗⼝和接收端主机反馈的窗⼝⼤⼩(接收窗口 < rwnd >)做⽐较, 取较⼩的值作为实际发送的窗口

当拥塞窗口超过这个阈值的时候,不再按照指数⽅式增⻓, ⽽是按照线性⽅式增⻓

当TCP开始启动的时候, 慢启动阈值等于窗⼝最⼤值;
在每次超时重发的时候, 慢启动阈值会变成原来的⼀半, 同时拥塞窗⼝置回1
这里写图片描述


拥塞窗口相关题


这里写图片描述
t 时刻拥塞窗口为8,则t+1时刻后阈值为4,拥塞窗口置为1,后续按2的指数增长,到达阈值时,开始每次+1,即后续10次的拥塞窗口为1,2,4,5,6,7,8,9,10,11发送窗口等于拥塞窗口与接收窗口中小的。故为10KB(选B)

这里写图片描述

第一次发送1,接收窗口返回15,第二次发送2,接收窗口返回13(16-1-2),,,故经历4RTT后接收窗口返回1,故选(A)


6 . 延迟应答

假设接收端缓冲区为1M. ⼀次收到了500K的数据; 如果⽴刻应答, 返回的窗⼝就是500K;但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;在这种情况下, 接收端处理还远没有达到⾃⼰的极限, 即使窗⼝再放⼤⼀些, 也能处理过来;如果接收端稍微等⼀会再应答, ⽐如等待200ms再应答, 那么这个时候返回的窗⼝⼤⼩就是1M;

窗⼝越⼤, 网络吞吐量就越⼤, 传输效率就越⾼. 我们的⺫标是在保证⺴络不拥塞的情况下尽量提⾼传输效率

延迟应答机制:
数量限制: 每隔N个包就应答⼀次;
时间限制: 超过最⼤延迟时间就应答⼀次;
⼀般N取2, 超时时间取200ms


7 . 捎带应答
(在延迟应答基础上)
将上一次请求的ACK数据和应用层的应答数据合并一条发送


8 . 面向字节流
概念:
创建⼀个TCP的socket, 同时在内核中创建⼀个 发送缓冲区 和⼀个 接收缓冲区;
调⽤write时, 数据会先写⼊发送缓冲区中;
如果发送的字节数太⻓, 会被拆分成多个TCP的数据包发出;
如果发送的字节数太短, 就会先在缓冲区⾥等待, 等到缓冲区⻓度差不多了, 或者其他合适的时机发送出去;
接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区,然后应⽤程序可以调⽤read从接收缓冲区拿数据;
另⼀⽅⾯, TCP的⼀个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这⼀个连接, 既可以读数据,也可以写数据. 这个概念叫做 全双⼯(读写不需要匹配)


粘包问题
(应用层)

站在传输层的⾓度, TCP是⼀个⼀个报⽂过来的. 按照序号排好序放在缓冲区中.
站在应⽤层的⾓度, 看到的只是⼀串连续的字节数据

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


TCP异常情况
进程终⽌: 进程终⽌会释放⽂件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
机器重启: 和进程终⽌的情况相同.
机器掉电/网线断开: 接收端认为连接还在, ⼀旦接收端有写⼊操作, 接收端发现连接已经不在了, 就会进⾏reset. 即使没有写⼊操作, TCP⾃⼰也内置了⼀个保活定时器, 会定期询问对⽅是否还在. 如果对⽅不在, 也会把连接释放.
另外, 应⽤层的某些协议, 也有⼀些这样的检测机制. 例如HTTP⻓连接中, 也会定期检测对⽅的状态. 例如QQ,在QQ断线之后, 也会定期尝试重新连接


TCP特点
可靠性:
> 校验和
序列号(按序到达)
确认应答
超时重发
连接管理
流量控制
拥塞控制

提⾼性能:

滑动窗⼝
快速重传
延迟应答
捎带应答

定时器 (超时重传定时器, 保活定时器, TIME_WAIT定时器等

TCP不可以UDP可以——广播


OSI七层模型:
https://blog.csdn.net/Romantic_C/article/details/81665591
网络套接字:
https://blog.csdn.net/Romantic_C/article/details/81704425
UDP服务器:
https://blog.csdn.net/Romantic_C/article/details/81705468
TCP服务器:
https://blog.csdn.net/Romantic_C/article/details/81707907
应用层:
https://blog.csdn.net/Romantic_C/article/details/81714161
传输层:
https://blog.csdn.net/Romantic_C/article/details/81747317
网络层:
https://blog.csdn.net/Romantic_C/article/details/81751255
数据链路层:
https://blog.csdn.net/Romantic_C/article/details/81777844

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值