TCP / IP 协议浅析

TCP / IP 协议浅析

fron http://kenby.iteye.com/blog/1013313

博客分类:
    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                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                            TCP Header Format

* TCP协议的Sequence Number是建立在传输的字节流之上,而不是建立在传输的报文段的序列之上,一个报文

段可以传输很多个字节。

* Sequence Number: 32 bits

    The sequence number of the first data octet in this segment (except

    when SYN is present). If SYN is present the sequence number is the

    initial sequence number (ISN) and the first data octet is ISN+1.

Sequence Number是该报文段首字节的字节流序号

* 当SYN比特设置为1时,表明这是一个请求连接的报文段,这时的Sequence Number为此次连接中传输字节的初始序号(ISN),而传输的时候第一个字节就编号为(ISN+1)

   当SYN比特设置为1时,可以在报文段中设置此次连接的一些选项,比如设置MSS,限制此次连接中对方每次传输的报文段最多只能承载MSS个字节的数据量。双方都可以

设置MSS,互相限制对方的报文段大小。

当SYN比特设置为1时,此报文段不包含任何数据

当SYN比特没有设置时,报文段中必然有数据,这时的Sequence Number为报文段首字节的序号

* Acknowledgment Number: 32 bits

    If the ACK control bit is set this field contains the value of the

    next sequence number the sender of the segment is expecting to

    receive.  Once a connection is established this is always sent.

只有当ACK设置为1,Acknowledgement Number才有意义。

A发给B一个SYN = 0, Sequence Number = 79, ACK = 1, Acknowledgement Number = 42的报文段,说明

A收到了序号在42之前的所有字节,A现在期望序号为42的字节,同时A此次向B发送序号为79的字节。

* 确认比特 ACK —— 只有当 ACK = 1 时确认号字段才有效。当 ACK = 0 时,确认号无效。

* 推送比特 PSH (PuSH) —— 接收 TCP 收到推送比特置 1 的报文段,就尽快地交付给接收应用进程,而不再等到整个缓存都填满了后再向上交付。

* 复位比特 RST (ReSeT) —— 当 RST = 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。

* 同步比特 SYN —— 同步比特 SYN 置为 1,就表示这是一个连接请求或连接接受报文。

三次握手

client:   SYN J

server: SYN K, ACK J+1

client:   ACK K+1

三次握手之前,服务器必须准备好接受外来的连接,通过系统调用 socket, bind 和 listen 这3个函数来完成。

第一次握手:客户端调用 connect 发送 SYN 分节给服务器。它告诉服务器客户端在此次连接中发送数据的

初始序号,例如初始序号位J,则客户端发送的第一个字节的编号就从 J+1 开始,通常 SYN 分节不携带

任何数据。SYN分节还可以设置 MSS 选项,限制对方发送给自己的最大分节大小。

第二次握手:服务器必须发送ACK,确认客户端的 SYN,同时自己也得发送一个 SYN,告诉客户端此次连接

自己发送数据的初始序列号。ACK和SYN都是在同一个分节发送的。

第三次握手:客户端回送ACK确认服务器的SYN,因为ACK的确认号是自己期待的下一个序列号,

所以每个SYN的确认号等于SYN的序列号加1.

关闭连接

client:   FIN M

server: ACK M+1

server: FIN N

client:   ACK N+1

(1) 假设客户端调用 close 主动关闭连接,引起TCP发送 FIN 分节,告诉服务器我的数据已发送完毕。

      客户端的TCP状态由 ESTABLISHED 变成 FIN_WAIT_1, 等待服务器的确认。

(2) 服务器收到FIN分节后,把它当作文件结束符传递给应用进程,然后发送ACK分节确认客户端的FIN

      服务器的TCP状态由 ESTABLISHED 变成 CLOSE_WAIT, 等待进程调用 close 关闭连接

      客户端收到ACK后,TCP 状态由 FIN_WAIT_1 变成 FIN_WAIT_2,  等待服务器的 FIN 

(3)  一段时间后,进程收到文件结束符,read 返回 0,表示数据读完了,然后调用 close 关闭 socket。

      引起 TCP 发送 FIN 分节给客户端。

       服务器的TCP状态由 CLOSE_WAIT 变成 LAST_ACK, 等待客户端的确认。

(4)  客户端收到 FIN 分节后回送 ACK 给服务器。

       客户端的 TCP 状态由 FIN_WAIT_2 变成 TIME_WAIT

       等到服务器收到客户端的ACK后,其状态由 LAST_ACK 变成 CLOSED

(5) 客户端在 TIME_WAIT 状态等待 2个 MSL 的时间,然后变成 CLOSED状态,自此,TCP连接全部关闭。

客户端关闭的时候需要等待3次:

第一次,FIN_WAIT_1, 等待服务器的ACK

第二次,FIN_WAIT_2, 等待服务器的FIN

第三次, TIME_WAIT, 等待时间为2*MSL,一般为1-4分钟,MSL是maximum segment lifetime

服务器关闭一次连接需要等待2次:

第一次, CLOSE_WAIT,  等文件结束符

第二次,LAST_ACK, 等待客户端的ACK

理解 TIME_WAIT 

TIME_WAIT 的等待时间为2*MSL,一般为1-4分钟,MSL是maximum segment lifetime,即分节最长生命时间。

为什么 客户端 收到 服务器的 FIN 分节后,不立即关闭连接,而是经历 TIME_WAIT 状态再关闭呢?

TIME_WAIT 状态有两个存在的理由:

(1) 可靠地实现 TCP 全双工连接的关闭

       客户端发送的 ACK 可能会丢失,这时服务器就得再次发送 FIN 分节。要是客户端立刻关闭连接,

       客户端将响应 一个 RST 给服务器,服务器认为这是一个错误。

(2) 让老的重复分节在网络中消逝

       假设一个 TCP 连接刚刚关闭,在相同的IP和相同的端口之间又建立一条新的 TCP 连接。那些老的TCP

       连接残留下来的分组可能会出现在新的连接中,并被新的连接误解成有效数据。 为了防止这种情况发生,

       在老的分组消逝之前,不允许创建新的tcp连接,所以设置 TIME_WAIT 状态专门等待老的分组在网络中

      消逝,TCP 不给处于 TIME_WAIT 状态的连接创建新的连接。TIME_WAIT 的持续时间是 MSL 的两倍,

      这就足以让分组在一个方向上经过 MSL 的时间丢弃,分组的应答经过另一个 MSL 的时间也被丢弃。

TCP/IP分组的大小及限制

IP协议头的格式如下所示:
   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    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

1. IP 数据包的大小

可以看出,Total Length字段有 16 个比特,表示的是整个IP数据包(包括ip协议头)的大小,最大是 65535 个字节。

2 TCP数据块的大小

TCP数据块的大小受对方设置的 MSS 所限制,数据块不能超过 MSS 个字节,在 TCP 协议头中,MSS

放在选项字段里,用16个比特表示,所以 MSS 最大是 65535个字节。但 MSS 一般不能取到 65535,

它最多等于 (IP包的最大值 - IP Header - TCP Header) = (65535 - 20 -20) = 65495 个字节。

3 如何防止分片

在数据链路层,以太网最大的数据帧是 1518 个字节,除去以太网的帧头14个字节和帧尾4个字节的

CRC校验值,剩下用来承载上层协议的地方就剩下 1500 个字节,这个值称为 MTU。也就是说

以太网最多能承载的IP数据包大小是 1500 个字节,如果 IP 数据包超过了 1500 个字节,就要进行分片。

为了防止IP分片,IP 数据包的大小不能超过 1500 个字节,减去20个字节的IP Header 和 20 个字节

的 TCP Header,TCP协议的数据块大小就不能超过 1460 个字节。所以在以太网中一般把 MSS 的值

设为 1460。

原文地址:https://www.cnblogs.com/tangr206/p/2975288.html