数据报文:ether-Ip-Udp-Tcp
IP数据包也叫IP报文分组,传输在ISO网络7层结构中的网络层,它由IP报文头和IP报文用户数据组成,IP报文头的长度一般在20到60个字节之间,而一个IP分组的最大长度则不能超过65535个字节。
下图为IP分组的报文头格式,报文头的前20个字节是固定的,后面的可变。
版本:占4位(bit),指IP协议的版本号。目前的主要版本为IPV4,即第4版本号,也有一些教育网和科研机构在使用IPV6。在进行通信时,通信双方的IP协议版本号必须一致,否则无法直接通信。
首部长度:占4位(bit),指IP报文头的长度。最大的长度(即4个bit都为1时)为15个长度单位,每个长度单位为4字节(TCP/IP标准,DoubleWord),所以IP协议报文头的最大长度为60个字节,最短为上图所示的20个字节。
服务类型:占8位(bit),用来获得更好的服务。其中的前3位表示报文的优先级,后面的几位分别表示要求更低时延、更高的吞吐量、更高的可靠性、更低的路由代价等。对应位为1即有相应要求,为0则不要求。
总长度:16位(bit),指报文的总长度。注意这里的单位为字节,而不是4字节,所以一个IP报文的的最大长度为65535个字节。
标识(identification):该字段标记当前分片为第几个分片,在数据报重组时很有用。
标志(flag):该字段用于标记该报文是否为分片(有一些可能不需要分片,或不希望分片),后面是否还有分片(是否是最后一个分片)。
片偏移:指当前分片在原数据报(分片前的数据报)中相对于用户数据字段的偏移量,即在原数据报中的相对位置。
生存时间:TTL(Time to Live)。该字段表明当前报文还能生存多久。每经过1ms或者一个网关,TTL的值自动减1,当生存时间为0时,报文将被认为目的主机不可到达而丢弃。使用过Ping命令的用户应该有印象,在windows中输入ping命令,在返回的结果中即有TTL的数值。
协议:该字段指出在上层(网络7层结构或TCP/IP的传输层)使用的协议,可能的协议有UDP、TCP、ICMP、IGMP、IGP等。
首部校验和:用于检验IP报文头部在传播的过程中是否出错,主要校验报文头中是否有某一个或几个bit被污染或修改了。
源IP地址:32位(bit),4个字节,每一个字节为0~255之间的整数,及我们日常见到的IP地址格式。
目的IP地址:32位(bit),4个字节,每一个字节为0~255之间的整数,及我们日常见到的IP地址格式。
由于Delphi里面没有位域这个概念,所以定义结构的时候只能整字节了,挺怀恋C++或者Erlang的,有位域定义出来和使用起来都很方便了
//IP包
TIPHeader = packed record
iph_verlen: byte; // 版本和长度
iph_tos: byte; // 服务类型
iph_length: word; // 总长度,2个无符号字节所以只能65535
iph_id: word; // 标识
iph_offset: word; // 标志和片偏移
iph_ttl: byte; // 生存时间
iph_protocol: byte; // 协议
iph_xsum: word; // 头校验和
iph_src: longword; // 源地址
iph_dest: longword; // 目的地址
end;
UDP报文格式:
源端口号和目的端口号如上和TCP的相同。
UDP长度:UDP报文的字节长度(包括首部和数据)。
UDP校验和: 检验UDP首部和数据部分的正确性。
TCP报文格式:
源端口: 数据发送方的端口号。
目的端口: 数据接受方的端口号。
序号:本数据报文中的的第一个字节的序号(在数据流中每个字节都对应一个序号)。
确认号:希望收到的下一个数据报文中的第一个字节的序号。
数据偏移:表示本报文数据段距离报文段有多远。
保留:顾名思义,用来保留给以后用的。
紧急比特URG:当值为1时表示次报文段中有需要紧急处理。
确认比特ACK:值为1时确认号有效,值为0时确认号无效。
复位比特RST:值为1时表示TCP连接存在严重的错误,需要重新进行连接。
同步比特SYN:值为1表示这是一个连接请求或连接接受报文。
终止比特FIN: 值为1表示要发送的数据报已经发送完毕,需要释放传送连接。
窗口字段:TCP连接的一端根据缓存空间的大小来确定自己接受窗口的大小,限制发送放的窗口上限。
检验和:用来检验首部和数据两部分的正确性。
紧急指针字段:本报文紧急数据的最后一个字节的序号。