传输层和网络层的checksum区别,TCP cksum为何包含伪首部
一直搞不清传输层和网络层的校验和为什么校验内容不一样,最近问了一些前辈,找寻了一些答案,总结一下自己的思考。
先说一下传输层(TCP)和网络层(IP)的校验和:
- TCP校验和有伪首部、TCP herder、数据段。而IP的校验和只覆盖IP header,不覆盖IP数据报中的任何数据。TCP校验和、IP校验和的计算方法是一致。
- TCP的校验和是必需的,而UDP的校验和是可选的。
- 12字节伪首部:源IP地址、目的IP地址、保留字节(置0)、传输层协议号(TCP是6)、TCP报文长度(报头+数据)。
先提出三个问题:
- 为什么IP算的cksum只有头部呢?TCP却包含数据?
- 这个伪首部啥意思,为什么叫'伪'?
- 为何TCP算的cksum又加上伪头部呢?
为什么IP算的只有ip header呢?TCP却包含数据?
让我们先回顾一下计算机网络里说到的TCP五层模型,现实中是把物理层和数据链路层放一起了,都叫链路层。
- 应用层 (application layer):应用进程提供服务
- 传输层 (transport layer):为进程提供通信服务,为上层提供端到端(最终用户到最终用户)的透明的、可靠的数据传输服务。拥塞控制,流控都在这。
- 网络层 (internet layer):为主机提供通信服务
- 数据链路层 (data link layer):为同一链路主机提供数据传输服务
- 物理层 (physical Layer):确保数据可以在各种物理媒介上进行传输,为数据的传输提供可靠的环境。
首先,其实每一层都有自己的校验方法?为什么?校验算法没法百分百保证正确,越早发现越早丢弃。
我自己的理解:每个层都是有自己负责的内容,按照这个思路去看。数据先加端口号封装传输层,传输层负责的是为进程通信确保了送到主机上正确的port(进程绑定的port)。加ip封装网络层,ip层只是负责送到正确的机器上。加mac封装物理层,控制网卡需要网卡驱动程序,网卡驱动从ip模块获得包后将其复制到网卡的缓存中,然后在头部加报头和起始帧分界符,末尾加上帧校验序列(循环冗余算法(CRC)生成的fcs校验序列)。经过网卡将数字信号转化为电信号,通过网线发送出去。这里负责的是真正传输内容。首先链路层这里是简单确保整个报文没有被改变,交换机会解析MAC然后校验这个fcs,这里链路层保证数据可靠专属。路由器收到之后会解析到ip header,计算fcs和ip校验和,也就是路由器里面相当于也有fcs保证数据的正确,尽管很羸弱,ip层的任务就是只确保ip是对的,就像贴在箱子上的快递单做的事情,不关心箱子里的东西对不对,当然路由器会查表封装新的MAC头从计算fcs。真正到了主机,也会校验fcs,ip校验和,到了传输层,需要向上交付数据,所以传输层这里校验和会包含数据段。
TCP/IP地分层,让每一层注重自己的事情,IP不会过问数据,TCP层需要保证数据,但是为什么链路层有了校验,还需要其它层保证呢?举个简单的例子,路由器拆了以太帧头之后放到自己的缓冲区,在缓存去里这个时候报文出错了,路由器吧错误的报文计算一下fcs,封装好,继续发,这样之后链路层再校验,也没问题,还是需要更上层的校验。
刚才说的这些校验都是低级的校验,TCP/IP提出的时代,设备能力还是很差的,只能用这种简单的CRC去校验,但比如一个"10 20"变成的"20 10",对于CRC是校验不出来的,因为CRC只管累加没问题。
这个伪首部啥意思,为什么叫'伪'?
12字节伪首部:源IP地址、目的IP地址、保留字节(置0)、传输层协议号(TCP是6)、TCP报文长度(报头+数据)。
计算checksum时,其实整个包的信息都可以获取,传输层直接从ip header拿出源ip、目的ip、传输协议号用来计算checksum,这些字段并不是在tcp报文里,所以是伪,只是计算时带上而已。
收端也是,收到之后连带这几个字段校验一下,实际上tcp报文并没有这几个字段的内容。
为何TCP算的cksum又加上伪头部呢?
这更算一个历史遗留问题,过去还没有光纤,没有现在这些可靠性高的传输技术,之前线路误码率非常高,为了确保数据包到收端的正确性,这又相当于多加了一点保证,并且几乎没有损失性能。
IPV6和IPV4
IPV6省略了IP层的校验和,引入了更加可靠的链路层错误检测和纠正机制。因为当前的设备不再像之前错误那么多,付出校验所有包的代价去转发,并不值得,有其他更好的错误检测,这样像路由器这样的网络设备,就不需要再校验了,提高了性能。
延伸
推荐读一下这个论文:https://zhuanlan.zhihu.com/p/55311553