一、网络层(L3)
1、IP协议概述
IP协议在两台主机之间提供了端到端的连接。网络层的主要功能有数据包的接收、发送、转发,如果数据包比MTU大,还会进行分段和重组。转发数据包也叫路由选择,为此Linux内核需要管理路由表
2、IP地址分类
IP地址分类 | IP范围 | 广播地址 | 私有IP范围 | 子网掩码 | 网络数 | 每个网络主机数 |
A类地址 | 1.0.0.1~126.255.255.254 | 126.255.255.255 | 10.0.0.0~10.255.255.255(即10.0.0.0/8) | 255.0.0.0 | 126 | 16777214 |
B类地址 | 128.0.0.1~191.255.255.254 | 191.255.255.255 | 172.16.0.0~172.31.255.255(即172.16.0.0/12) | 255.255.0.0 | 16382 | 65534 |
C类地址 | 192.0.0.1~223.255.255.254 | 223.255.255.255 | 192.168.0.0~192.168.255.255(即192.168.0.0/16) | 255.255.255.0 | 2097150 | 254 |
D类地址 | 224.0.0.0~239.255.255.255 | 用于多播,不分配给主机。多播允许单台主机同时向Internet多台主机发送数据流,通常用于音视频流 | ||||
E类地址 | 240.0.0.0~255.255.255.254 | 保留地址,不分配给主机,不用于一般用途 |
特殊地址
0.0.0.0在服务器配置中表示监听所有可用的IPv4地址,在路由配置中表示默认路由,当路由表中没有找到与数据包匹配的路由项时,数据包将发往默认路由指向的目的主机
1.0.0.0用于指示没有特定IP的主机,比如主机通过DHCP获取地址时,最初会用1.0.0.0作为源IP,直到收到有效的IP地址为止
127.0.0.0~127.255.255.255整个127网段表示回环地址,不会分配给主机使用
3、IPv4报头
IPv4报头前20字节是固定的,另外还有40字节是可选的,最长可达60字节
IPv4报头在内核中的表示
// include/linux/ip.h
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
- ihl:IPv4报头长度,以4字节为单位。最短为20字节(不包含任何选项,此时ihl为5),最长为60字节(对应ihl为15)
- version:必须为4
- tos:前6位表示区分服务,第7~8位为显式拥塞通知(不知道是啥东东,想详细了解的话可参考RFC2474、RFC3168)
- tot_len:包括报头在内的数据包总长度,单位为字节。16位可表示的最大长度为64KB,RFC791规定,数据包最短不得少于576字节
- id:IPv4报头标识。对数据包分段时,所有分段的id必须相同;对于分段后的数据包,要根据各分段的id进行重组
- frag_off:后13位表示分段偏移量,第一个分段中,偏移量为0,偏移量以8字节为单位。前3位的含义如下:
001 - 表示后面还有其他分段(More Fragments,MF),除最后一个分段外,其他分段都必须设置该标志
010 - 表示不分段(Don't Fragment,DF)
100 - 表示拥塞
- ttl:存活时间,这是一个跳数计数器,每个转发节点都会将ttl减1,当ttl变为0时,将丢弃数据包,并发回一条ICMPv4超时消息
- protocol:第4层协议,如IPPROTO_TCP、IPPROTO_UDP
协议编号 | 协议名 | 协议描述 | 参考 |
0 | Dummy protocol for TCP | ||
1 | ICMP | Internet Control Message | RFC792 |
2 | IGMP | Internet Group Management | RFC1112 |
4 | IP-in-IP tunnels | ||
6 | TCP | Transmission Control Protocol | RFC793 |
8 | EGP | Exterior Gateway Protocol | RFC888 |
12 | PUP | PUP | |
17 | UDP | User Datagram Protocol | RFC768 |
22 | XNS IDP protocol | ||
33 | Datagram Congestion Control | ||
41 | IPv6 | IPv6-in-IPv4 tunnelling | |
46 | RSVP | ||
47 | Cisco GRE tunnels | RFC1701,1702 | |
50 | ESP | Encapsulation Security Payload | |
51 | AH | Authentication Header protocol | |
94 | IP option pseudo header for BEET | ||
103 | Protocol Independent Multicast | ||
108 | Compression Header protocol | ||
132 | Stream Control Transport Protocol | ||
136 | UDP-Lite | RFC3828 | |
255 | Raw IP packets |
- check:校验和,仅根据IPv4报头计算得到
- saddr:源IPv4地址
- daddr:目标IPv4地址
4、接收IPv4数据包
5、发送IPv4数据包
6、分段
网络接口对数据包的长度进行了限制,在10/100/1000Mbps以太网中,通常为1500B。当发送大于网卡MTU的数据包时,需要将其划分为较小的片段,这是在方法ip_fragment()中完成的
7、重组
重组指的是将数据包的所有分段重组为一个缓冲区,这些分段的IPv4报头中的id都相同。处理分组的主方法是在ip_local_deliver()中调用ip_defrag()
8、转发
数据包转发的主处理程序是ip_forward()
二、传输层(L4)
1、TCP协议:为应用层提供可靠的、面向连接的、基于字节流的服务
可靠的:TCP协议使用超时重传、数据确认等方式来确保数据被正确的传送给目的端
面向连接:TCP协议要求通信双方必须先建立TCP连接(三次握手)
基于字节流:基于字节流的数据没有边界(长度)的限制,它源源不断地从通信的一端流入另一端。发送端可以逐个字节地向数据流中写入数据,接收端也可以逐个字节地将他们读出。
《UNIX网络编程》2.6.4 TCP状态转换图
2、UDP协议:为应用层提供不可靠的、无连接的、基于数据包的服务
不可靠:意味着UDP无法保证数据从发送端正确正确地传送到目的端。如果数据在中途丢失,或者目的端通过数据校验发现数据错误而丢弃,UDP协议只是简单地通知应用程序发送失败。因此,使用UDP协议的应用程序通常要自己处理确认重传等逻辑
无连接:通信双方不保持一个长久的联系,因此应用程序每次发送数据都要明确指出接收端的地址。
基于数据包:每个UDP数据报都有一个长度,接收端必须以该长度为最小单位一次性读出,否则数据被截断。
三、应用层
应用层的协议主要有:http、ftp、ssh、telnet、DNS等
四、SOCKET编程接口
socket的这组API提供如下两方面的功能
1、将应用程序数据从用户缓冲区复制到TCP/UDP内核缓冲区,让内核来发送数据。或者是从内核TCP/UDP接收缓冲区中复制数据到用户缓冲区,已读取数据。
2、应用程序可以通过它们来修改内核中各层协议的某些头信息或其他数据结构,从而精细地控制底层通信的行为。
五、IP路由(IP数据报文的转发)
IP协议的一个核心任务就是数据报路由,即发送数据报到目标机器的路径。
一个路由器其实就是一个超小型电脑,操作系统大多为Linux。普通主机通常不会转发IP数据报,但是通过配置可以使普通主机具备路由器的功能。
内核的网络层维护着一张路由表,当主机接收到数据报文时,该路由表将决策接下来应该做什么操作:
1、首先检查报文中的目标主机IP地址是否与本机的IP地址相同,如果相同,那么报文被发送给传输层,进而发送给应用层。如果不同,数据报文将进行转发或者丢弃。
2、第一步,检查路由表中第一列的IP地址是否有与报文中目标主机的IP地址完全相同的,如果找到直接发给下一个路由器。
2、没找到完全相同的IP,则查找第二列网关ID,找到的话数据报就被发送到指定的路由器。
3、如果都没找到,则发往默认路由器。如果没有默认路由器,回传ICMP错误,数据报被丢弃。
七、TCP头部结构
九、网络中数据丢包的可能原因
1、发送端发送数据的速度太快,接收端来不及接收导致数据丢失。(常见于使用UDP协议的应用程序)
2、路由跳数超出发送端设置的最大值,数据被路由器丢弃。在IP协议的头部有一个1字节的TTL字段,表示数据报到达目的地之前允许经过的路由器跳数,数据报在转发过程中每经过一个路由,该值就被路由器减1。当TTL字段被减为0时,路由器将丢弃数据报。
3、物理信道中固有的热噪声或突击噪声造成数据失真,在接收端通过校验码检查出数据传送发生错误,那么数据被接收端丢弃。