图1 每层的数据由头部分和负载部分组成
图2 TCP/IP中将HTML数据最后封装在以太网帧中传送
图3 IP数据包结构
struct iphdr { //IP层头部 #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; __u16 tot_len; __u16 id; __u16 frag_off; __u8 ttl; __u8 protocol; __u16 check; __u32 saddr; __u32 daddr; /*The options start here. */ };
Fragmentation一个实例截图:
从以上两图可知,并没有用一个ip数据报并对它进行分片传送,而是用了两个ip数据报,为什么?
IP Fragmentation 参考资料:http://www.cisco.com/c/en/us/support/docs/ip/generic-routing-encapsulation-gre/25885-pmtud-ipfrag.html
根据此资料,ip分片是会带来很多问题的, 需要避免ip数据报进行分片传输!
那么ip数据报的大小是怎么确定好然后就不需要分片了的呢?
以上参考资料上的说明如下:
The TCP Maximum Segment Size (MSS) defines the maximum amount of data that a host is willing to accept in a single TCP/IP datagram. This TCP/IP datagram might be fragmented at the IP layer. The MSS value is sent as a TCP header option only in TCP SYN segments. Each side of a TCP connection reports its MSS value to the other side. Contrary to popular belief, the MSS value is not negotiated between hosts. The sending host is required to limit the size of data in a single TCP segment to a value less than or equal to the MSS reported by the receiving host.
Originally, MSS meant how big a buffer (greater than or equal to 65496K) was allocated on a receiving station to be able to store the TCP data contained within a single IP datagram. MSS was the maximum segment (chunk) of data that the TCP receiver was willing to accept. This TCP segment could be as large as 64K (the maximum IP datagram size) and it could be fragmented at the IP layer in order to be transmitted across the network to the receiving host. The receiving host would reassemble the IP datagram before it handed the complete TCP segment to the TCP layer.
实例图如下:
图4 TCP包结构
struct tcphdr { //TCP协议头部 __u16 source; __u16 dest; __u32 seq; __u32 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 __u16 window; __u16 check; __u16 urg_ptr; };
图5 UDP包结构
struct udphdr { //UDP协议头部 __u16 source; __u16 dest; __u16 len; __u16 check; };
/* * 以太网帧头结构 This is an Ethernet frame header. */ struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ unsigned short h_proto; /* packet type ID field */ };
struct arphdr { unsigned short ar_hrd; /* format of hardware address */ unsigned short ar_pro; /* format of protocol address */ unsigned char ar_hln; /* length of hardware address */ unsigned char ar_pln; /* length of protocol address */ unsigned short ar_op; /* ARP opcode (command) */ /* The rest is variable in size, according to the sizes above. */ #if 0 unsigned char ar_sha[]; /* sender hardware address */ unsigned char ar_spa[]; /* sender protocol address */ unsigned char ar_tha[]; /* target hardware address */ unsigned char ar_tpa[]; /* target protocol address */ #endif /* not actually included! */ };
struct icmphdr { //ICMP头结构 __u8 type; __u8 code; __u16 checksum; union { struct { __u16 id; __u16 sequence; } echo; __u32 gateway; struct { __u16 __unused; __u16 mtu; } frag; } un; };
struct igmphdr //IGMP头结构 { __u8 type; __u8 code; /* For newer IGMP */ __u16 csum; __u32 group; };