TCP/IP协议栈 头部参数

与世无争的帅哥 提交于 2019-12-09 11:22:01


IP头部:20个字节

TCP头部:20字节

UDP头部:8字节

ICMP头部:4字节


TTL:经过一个路由器就减1,当TTL值为0时,路由器就丢弃这个包,然后发送ICMP包给源主机。

默认情况下,Linux系统的TTL值为64或255,Windows NT/2000/XP系统的TTL值为128,Windows 98系统的TTL值为32,UNIX主机的TTL值为255。


以太网EthernetII最大的数据帧是1518字节,刨去以太网帧的帧头(DMAC目的地址MAC48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和帧尾CRC校验部分4Bytes(有时候大家也把它叫做FCS),那么剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes. 这个值我们就把它称之为MTU。


以太网数据包长度:(64~1518)

MTU: Maxitum Transmission Unit 最大传输单元 (46~1500)

MSS:Maxitum Segment Size 最大分段大小(MTU-IP header size-TCP header size)(1460=1500-20-20)

MSS解释:

        MSS最大传输大小的缩写,是TCP协议里面的一个概念。MSS就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。



图中括号中的数字代表的是当前域所占的空间大小,单位是bit位。

黄色的是数据链路层的头部,一共18字节

绿色的部分是IP头部,一般是20字节

紫色部分是TCP头部,一般是20字节

最内部的是数据包内容

黄色部分:链路层

目的MAC当前step目的主机的mac地址

MAC当前step的源主机的mac地址

类型:指定网络层所用的协议类型,通常是IP协议,0x0800


绿色部分:网络层,这里用的是IP包头格式

版本:记录数据报属于哪一个版本的协议,如IPv4IPv6

首部长度:指明IP头部长度,单位是字,也就是两个字节。该域的值最小为5,就是标准的头部长度;最大为15,表明有扩展部分。

服务类型:用来区分不同服务的需要

数据报总长:包含IP头部的数据报的总长度。注意,这里不包括链路层的头部,目前最大值是65535字节。

分组ID这个域的作用是当一个大的数据报被拆分时,拆分成的小的数据段的这个域都是一样的。

标记:共三个bit,第一个未使用;第二个DF(Don’t Fragment),设置成1表示这个数据包不能被分割,这个是针对路由器的一条指令;第三个MF(MoreFragment),如果一个数据包被分割了,那么除了最后一个分段以外的所有分段都必须设置为1,用来表示后面还有更多的分段没有到达,最后一个设置为0,用来表示分割的段全部到达。

段偏移量:这个域有13bit,也就是每一个数据报最多有8192个分段。每一个分段的长度必须是8字节的倍数,也就是说8字节是分段的基本单位,当然分组的最后一个段不做限制。这样最大的数据报长度为8*8192=65536字节,比目前限制的最大数据报长度还多1,能够满足对网络中所有数据报传送的需求。

生存时间:这是一个生存期计数器,最大为255s,但是实际上使用的时候用作跳数计数器,当值为0时数据报被丢弃,用来避免一个数据报过久的逗留在网络中。

高层协议:这里和链路层的类型作用相同,用来表示更高层的协议,这个数据报里是TCP

首部校验和:IP头部的校验和

IP地址:数据报来源主机的IP地址

目的IP地址:数据报目的主机的IP地址


紫色部分:传输层,这里用的是TCP协议

源端口号:数据报来源主机的端口号

目的端口号:数据报目的主机的端口号

注意:源IP地址,目的IP地址,源端口号,目的端口号这四个字段唯一的确定了一个TCP链接。

TCP序号(sq)发送的TCP的序号,从0开始,实际中这个值就是发送的数据报中内容的字节数,比如我发送的第一个报中sq=0,数据报内容20字节,那么下一个数据报的sq就应该是21

捎带的确认(ack)确认收到上一个数据报,然后act的值是指定自己想要收到的下一个数据报的sq,比如我收到一个数据报的sq=0,数据报内容20字节,那么我的ack就应该是21,用来标明我sq=0,内容为20字节的数据报已经收到,我接下来期望收到的是sq=21的数据报。

首部长度:IP头部的长度域类似,这个域用来标明TCP头部的长度,单位也是字。

保留:6bit未使用的域

Flag从左到右,[URG|ACK|PSH|RST|SYN|FIN]

ACK设置为1表示前面的确认(ack)是有效的,否则前面的确认应被忽略。

PSH表示要求对方在接到数据后立即请求递交给应用程序,而不是缓冲起来直到缓冲区收满为止。

RST用于重置一个已经混乱的连接。

SYN用于建立连接的过程。在链接请求中,SYN=1ACK=0表示该数据段没有使用捎带的确认域。链接应答则捎带了一个确认,即SYN=1ACK=1.本质上SYN位是用来表示CONNECTION
REQUEST
CONNECTION ACCEPTED,然后进一步用ACK来区分是请求还是应答,的确很高明。

FIN用来释放一个连接。它表示发送方已经没有数据要传输了。然后,在关闭一个连接后,关闭进程可能会在一段不确定的时间内继续接收到数据。SYNFIN数据段都有TCP序号,从而保证了这两种数据段被按照正确的顺序来进行处理。

窗口大小:指定了从被确认的字节算起可以发送多少个字节。要深入理解这个域的含义,可以参看TCP用色控制和慢启动算法

校验和:校验范围包括TCP头、数据报内容和概念性伪头部。概念性伪头部又包括源IP,目的IPTCP协议号。

紧急指针:指向数据报中紧急数据最后一个字节的下一个字节。




//以太网头部
struct ethhdr {
	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
	__be16		h_proto;		/* packet type ID field	*/
} __attribute__((packed));
// arp头部
struct arphdr {
	__be16		ar_hrd;		/* format of hardware address	*/
	__be16		ar_pro;		/* format of protocol address	*/
	unsigned char	ar_hln;		/* length of hardware address	*/
	unsigned char	ar_pln;		/* length of protocol address	*/
	__be16		ar_op;		/* ARP opcode (command)		*/

#if 0
	 /*
	  *	 Ethernet looks like this : This bit is variable sized however...
	  */
	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/
	unsigned char		ar_sip[4];		/* sender IP address		*/
	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/
	unsigned char		ar_tip[4];		/* target IP address		*/
#endif

};

//IP头部
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. */
};


//UDP头部
struct udphdr {
	__be16	source;
	__be16	dest;
	__be16	len;
	__sum16	check;
};


//TCP头部
struct tcphdr {
	__be16	source;
	__be16	dest;
	__be32	seq;
	__be32	ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
	__u16	res1:4,
		doff:4,
		fin:1,
		syn:1,
		rst:1,
		psh:1,
		ack:1,
		urg:1,
		ece:1,
		cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
	__u16	doff:4,
		res1:4,
		cwr:1,
		ece:1,
		urg:1,
		ack:1,
		psh:1,
		rst:1,
		syn:1,
		fin:1;
#else
#error	"Adjust your <asm/byteorder.h> defines"
#endif	
	__be16	window;
	__sum16	check;
	__be16	urg_ptr;
};








易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!