tcp/ip 学习记录 传输层
TCP是面向连接的、可靠的流协议。
UDP是不具有可靠性的数据报协议。
根据端口号就可以识别在传输层上一层的应用层中所要进行处理的具体程序。
TCP/IP、UDP/IP通信中,通常采用5个信息来识别一个通信。分别为:源IP地址、目标IP地址、协议号、源端口号、目标端口号。只要其中一项不同,那么就会被认为是不同的通信。
动态分配的端口号取值范围在49152至65535之间。
数据到达IP层后,会先检查IP首部中的协议号,再传递给协议的模块。如果是TCP则传递给TCP模块、UDP则传给UDP模块,它们再做相应的端口处理。
TCP可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制,这些在UDP中是没有的。
TCP通过肯定的确认应答(ACK)实现可靠的数据传输。未收到确认应答并不意味着数据一定丢失,也可能是返回的确认应答在途中丢失。
在BSD的Unix和Windows中,超时以0.5秒为单位,最初的数据包还不知道往返时间,所以重发超时(RTO)时间最初为6秒。
数据在被重发之后若还是得不到响应,则再次进行发送,此时,RTO会以2倍、4倍的指数形式增加。
数据不会被无限次重发,达到一定重发次数后,会强制关闭连接。
在建立TCP连接的同时,也可以确定发送数据包的单位,我们称之为最大消息长度(Mss:Maximum Segment Size)。最理想的情况是,最大消息长度正好是IP中不会被分片处理的最大数据长度。
接收端向发送端通知自己可以接受数据的大小,于是发送端会发送不超过这个限度的数据。该大小限度称为接收窗口。
接收端接收数据时,窗口大小的值也会随之减小并通知给发送端,从而减小数据发送量,完成TCP流控制。在处理完窗口的数据后会进行窗口更新通知。
发送端会时不时(每个RTO时间)的发送一个叫做窗口探测的数据段,该数据段仅含一个字节以获取最近的接收窗口大小,防止窗口大小更新的数据包丢失。
发送窗口决定了一口气能发送多少字节,而MSS决定了这些字节要分多少个包发完。
发送方在一个窗口发送n个包,不一定会收到n个确认包,一半会少一些,因为TCP可以累积起来确认。
RTO:从发出原始包到重传该包的这段时间成为RTO(超时重传)。
快速重传:当发送方收到3个或以上的Dup Ack时,就意识到相应的包已经丢失,从而立即重传它,该过程叫做快速重传。
延迟确认应答:接收数据的主机每次都立刻回复确认应答的话,可能会返回一个较小的窗口,因为刚接收完数据,缓冲区已满。TCP传输中,绝大多数是每两个数据段返回一次确认应答。
UDP包结构:
字段 | 长度 | 意义 |
源端口号(Source Port) | 16bit | 源端口号 |
目标端口号(Destination Port) | 16bit | 目标端口号 |
包长度(Length) | 16bit | 单位为字节,保存了UDP首部的长度与数据的长度之和 |
校验和(Checksum) | 16bit | 为了提供可靠的UDP首部和数据而设计 |
数据部分(Data) | 变长 | 数据 |
TCP包结构:
字段 | 长度 | 意义 |
源端口号(Source Port) | 16bit | 源端口 |
目标端口号(Destination Port) | 16bit | 目标端口 |
序列号(Sequence Number) | 32bit | 指发送数据的位置,由握手时随机生成,不是从0开始 |
确认应答号(Acknowledgement Number) | 32bit | 指下一次应该接收的数据的序列号 |
数据偏移(Data Offset) | 4bit | 单位为4字节,表示数据应该从TCP包的哪个位置开始,通常tcp头为20字节 |
保留(Reserved) | 4bit | 为了以后扩展 |
控制位(Control Flag) | 8bit | 下面表格介绍 |
窗口大小(Window Size) | 16bit | 可接收数据大小 |
校验和(Checksum) | 16bit | 确认完整性 |
紧急指针(Urgent Pointer) | 16bit | 只有在URG控制位为1时有效 |
可选项(Options) | 变长 | 比如MSS、Window Scale、SACK(Selection ACKnowledgement) |
填充(Padding) | 变长 | 在有可选项Options的情况下,首部长度可能不是32bit的整数倍,此时填充0来调整为32bit的整数倍 |
数据部分(Data) | 变长 | 数据 |
控制位:
控制位字段 | 意义 |
CWR(Congestion Window Reduced) | 与ECE标识都用于IP首部的ECN字段,ECE标识为1时,则通知对方已将拥塞窗口缩小 |
ECE(ECN-Echo) | 置为1会通知通信对象,从对方到这边的网络又拥塞 |
URG(Urgent Flag) | 为1时,表示包中有需要紧急处理的数据 |
ACK(Acknowledgement Flag) | 为1时,确认应答的字段变为有效,TCP规定,除了最初建立连接时的SYN包之外,该位必须为1 |
PSH(Push Flag) | 为1时,表示需要将收到的数据立刻传给上层应用协议,为0时,则不需要立即传,而是先进行缓存 |
RST(Reset Flag) | 为1时,表示TCP连接中出现异常必须强制断开连接 |
SYN(Synchronize Flag) | 用于建立连接 |
FIN(Fin Flag) |
该位为1时,表示不会再有数据发送,希望断开连接 |
另外,在比较TCP/UDP的时候,会发现UDP指名了包的长度,而TCP却没有指明,为什么会这样呢?这是因为UDP是无连接的,你发包的时候必须要告诉对方你发了多长,要不对方不知道它应该接收多少,该处理多长。
UDP没有Seq和Ack的概念,无法维持一个连接,省去了建立连接的负担;
1、UDP不像TCP一样在乎双方MTU的大小,所以当数据超过MTU时,由网络层负责分片。
2、UDP没有重传机制,所以丢包由应用层来处理。
3、分片机制存在弱点,会成为黑客的攻击目标(黑客持续快速的发送flag为1的UDP包)。