1.IP Header
如下是RFC791规定的格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Version(版本): 4bit, 表示IP协议实现的版本号,当前是IPV4, 即0100
IHL(报头长度): 4bit, 表示头部的长度, 有多少个32比特.如果不包含Options(选项字段), 则长度为(5 * 32bit = 160bit)20字节, 最长为(15 * 32bit = 480bit)60字节
Type of Service(服务类型): 8bit, 其中前3bit为优先权字段,现已弃用. 第8bit保留. 第4至7字段分别表示延迟、吞吐量、可靠性、花费.当它们取值为1时分别表示要求最小延迟、最大吞吐量、最高可靠性、最小费用. 同时只能其中之一为1. 可以全为0表示一般服务. 服务类型声明了数据被网络系统传输时可以被怎样处理.
Total Length(总长度字段): 16bit. 表示整个数据报的长度, 最大长度65535字节.
Idenfification(标示): 16bit. 用来唯一地标识主机发送的每一份数据报。通常每发一份报文,它的值会加1。
Flags(标记): 3bit 第一位不使用 第二位DF(Don't Fragment)设为1时表示不能对该上层数据包分片,如果不分片无法转发,路由器会丢弃该数据返回一个错误. 第三位时MF(More Fragment),当路由器对上层数据包分段,则路由器会在除最后一个分段外所有分段该位置为1
Fragment Offset(片偏移): 13bit. 在对上层数据包分段后, 该字段表示当前IP包在其中的序列. 保证了目标路由器在接收到IP包后能还原上层数据. 若其中一个分段丢失,则包含该分段的整个上层数据包都会要求重传.
TTL(生存期): 8bit,用来表示该数据报文最多可以经过的路由器数,没经过一个路由器都减1,直到为0数据包丢掉。这个字段可以防止由于故障而导致IP包在网络中不停被转发。
Protocol(协议字段): 8bit. 标示IP层所封装的上层协议类型, 如传输层TCP/UDP/ICMP/IGMP
Header checksum(头部校验和字段): 16bit. 内容是根据IP头部计算得到的校验和码. 计算方法是:对头部中每个16bit进行二进制反码求和. (和ICMP、IGMP、TCP、UDP不同,IP不对头部后的数据进行校验).
将checksum字段置为0
对Header中每16bit做为一个值进行相加
相加的进位加到低16位上
对结果取反
赋值时,转换为网络字节序
Source Address & Dest Address: 源地址和目的地址. 各占32字节(IPV4).
Option(选项字段): 32bit. 用来定义一些任选项:如记录路径、时间戳等。这些选项很少被使用,同时并不是所有主机和路由器都支持这些选项。可选项字段的长度必须是32比特的整数倍,如果不足,必须填充0以达到此长度要求。
Checksum计算方法如下:
struct ip_header //小端模式__LITTLE_ENDIAN
{
unsigned char ihl:4; //ip header length
unsigned char version:4; //version
u_char tos; //type of service
u_short tot_len; //total length
u_short id; //identification
u_short frag_off; //fragment offset
u_char ttl; //time to live
u_char protocol; //protocol type
u_short check; //check sum
u_int saddr; //source address
u_int daddr; //destination address
};
u_short get_ip_checksum(char* ip_hdr)
{
char* ptr_data = ip_hdr;
u_long tmp = 0;
u_long sum = 0;
for (int i=0; i<20; i+=2)
{
tmp += (u_char)ptr_data[i] << 8;
tmp += (u_char)ptr_data[i+1];
sum += tmp;
tmp = 0;
}
u_short lWord = sum & 0x0000FFFF;
u_short hWord = sum >> 16;
u_short checksum = lWord + hWord;
checksum = ~checksum;
return checksum;
}
2.TCP Header
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
源(Source Port)、目标(Destination Port)端口号字段:占16bit. TCP协议通过使用"端口"来标识源端和目标端的应用进程。端口号可以使用0到65535之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在"众所周知的端口"(Well-Know Port)为用户提供服务。
顺序号字段(Sequence Number): 32bit. 用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。
确认号字段(Acknowledgment Number): 32bit. 只有ACK标志为1时,该字段才有效. 表示目标端所期望收到源端的下一个数据字节
头部长度字段(Data Offset): 4bit. 标示头部长度, 即头部占多少个32bit. 没有选项字段时,该字段值为20字节(5 * 32bit = 160bit). 最长可以有60字节(15 * 32bit = 480bit)
保留字段(Reserved): 6bit. (Reserved 3bit, Nonc 1bit, Congestion Window Reduced (CWR) 1bit, ECN-Echo 1bit)
标志位字段(U、A、P、R、S、F): 占6bit
URG: 紧急指针字段有效
ACK: 确认序号有效
PSH: 接收方应该尽快将这个报文交给应用层(数据传输)
RST: 重建连接
SYN: 发起一个连接
FIN: 释放一个连接
窗口大小(Window): 16bit. 此字段用来进行流量控制。单位为字节数,这个值是本机期望一次接收的字节数。
TCP校验和字段(Checksum): 16bit. 对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。
紧急指针字段(Urgent Pointer):占16比特. 它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号
选项字段:占32比特。可能包括"窗口扩大因子"、"时间戳"等选项。
选项字段: 目前定义在rfc793 中有三个kind。详细描述的可查看 https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml
Currently defined options include (kind indicated in octal):
Kind Length Meaning
---- ------ -------
0 - End of option list.
1 - No-Operation.
2 4 Maximum Segment Size.
3.UDP Header
1 | 2 | 3 | 4
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Source Port | Dest Port
-----------------------------------------------------------------
Data Length | Checksum
-----------------------------------------------------------------
Data
...
-----------------------------------------------------------------
- Source Port(源端口号): 在需要对方回信时选用。不需要时可用全0
- Dest Port(目标端口号): 在终点交付时必须使用到
- Data Length(UDP数据报长度): 长度包含首部和数据, 最小值为8字节
- Checksum(校验和): 检测UPD数据报在传输中是否有错, 有错就丢弃. 该字段可选,当源主机不想计算校验和,则直接令该字段为全0.
当传输层从IP层收到UDP数据报时,就根据首部中的目的端口,把UDP数据报通过相应的端口,上交给进程。如果接收方UDP发现收到的报文中目的端口号不正确(即不存在对应端口号的应用进程),就丢弃该报文,并由ICMP发送“端口不可达”差错报文交给发送方。
UDP特点:
- UDP无需建立连接, 因此UDP不会引入建立连接的时延.
- 无连接状态.TCP需要在端系统中维护连接状态。此连接状态包括接受和发送缓存、拥塞控制参数和确认号和序号的参数。而UDP不维护连接状态,也不跟踪这些参数.
- 分组首部开销更小。TCP有20字节的的首部开销,而UDP只有8个字节的首部开销。
- 没有拥塞控制,时延较小
- 不保证可靠交付,而是保证最大努力交付. 可靠性靠应用层来解决
- 面向报文的,一次交付一个报文. 对应用层交付的报文,添加首部后就交给IP层.不合并、不拆分
- 更适应用一次传输数据比较小的网络应用如DNS、SNMP等. 或者对可靠性要求不高,但是对实时性要求比较高的应用,如直播
UDP Checksum计算: