TCP 的三次握手
TCP 是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连
接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如 IP 地址、端口号等。
TCP 可以看成是一种字节流,它会处理 IP 层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在 TCP 头部。
TCP 提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用四次挥手
来关闭一个连接。
三次握手的目的是保证双方互相之间建立了连接。
三次握手发生在客户端连接的时候,当调用conncet(),底层会通过TCP协议进行三次握手。
ACK 是用来做确认的,SYN用来做连接,FIN用来做四次挥手的
-
16 位端口号(port number):告知主机报文段是来自哪里(源端口)以及传给哪个上层协议或
应用程序(目的端口)的。进行 TCP 通信时,客户端通常使用系统自动选择的临时端口号。 -
32 位序号(sequence number):一次 TCP 通信(从 TCP 连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号。假设主机 A 和主机 B 进行 TCP 通信,A 发送给 B 的第一个TCP 报文段中,序号值被系统初始化为某个随机值 ISN(Initial Sequence Number,初始序号值)。那么在该传输方向上(从 A 到 B),后续的 TCP 报文段中序号值将被系统设置成 ISN 加上该报文段所携带数据的第一个字节在整个字节流中的偏移。例如,某个 TCP 报文段传送的数据是字节流中的第 1025 ~ 2048 字节,那么该报文段的序号值就是 ISN + 1025。另外一个传输方向(从B 到 A)的 TCP 报文段的序号值也具有相同的含义。
-
32 位确认号(acknowledgement number):用作对另一方发送来的 TCP 报文段的响应。其值是收到的 TCP 报文段的序号值 + 标志位长度(SYN,FIN) + 数据长度 。假设主机 A 和主机 B 进行TCP 同信,那么 A 发送出的 TCP 报文段不仅携带自己的序号,而且包含对 B 发送来的 TCP 报文段的确认号反之,B 发送出的 TCP 报文段也同样携带自己的序号和对 A 发送来的报文段的确认序号
-
4 位头部长度(head length):标识该 TCP 头部有多少个 32 bit(4 字节)。因为 4 位最大能表示15,所以 TCP 头部最长是60 字节。
-
6 位标志位包含如下几项:
— URG 标志,表示紧急指针(urgent pointer)是否有效。
— ACK 标志,表示确认号是否有效。我们称携带 ACK 标志的 TCP 报文段为确认报文段。
— PSH 标志,提示接收端应用程序应该立即从 TCP 接收缓冲区中读走数据,为接收后续数据腾
出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在 TCP 接收缓冲区中)。
— RST 标志,表示要求对方重新建立连接。我们称携带 RST 标志的 TCP 报文段为复位报文段。
— SYN 标志,表示请求建立一个连接。我们称携带 SYN 标志的 TCP 报文段为同步报文段。
— FIN 标志,表示通知对方本端要关闭连接了。我们称携带 FIN 标志的 TCP 报文段为结束报文段。 -
16 位窗口大小(window size):是 TCP 流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
-
16 位校验和(TCP checksum):由发送端填充,接收端对 TCP 报文段执行 CRC 算法以校验TCP 报文段在传输过程中是否损坏。注意,这个校验不仅包括 TCP 头部,也包括数据部分。这也是 TCP 可靠传输的一个重要保障。
-
16 位紧急指针(urgent pointer):是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一个字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP 的紧急指针是发送端向接收端发送紧急数据的方法。
通过tcpdump的使用来了解tcp三次握手及四次挥手
qz@ubuntu:~$ sudo tcpdump -i lo -nt 'src 192.168.182.144' and 'dst 192.168.182.144' -nn -x
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 192.168.182.144.41202 > 192.168.182.144.9999: Flags [S], seq 3038065702, win 65495, options [mss 65495,sackOK,TS val 2547077140 ecr 0,nop,wscale 7], length 0
0x0000: 4500 003c dd63 4000 4006 6ee6 c0a8 b690
0x0010: c0a8 b690 a0f2 270f b515 3426 0000 0000
0x0020: a002 ffd7 eea0 0000 0204 ffd7 0402 080a
0x0030: 97d1 5014 0000 0000 0103 0307
IP 192.168.182.144.9999 > 192.168.182.144.41202: Flags [S.], seq 2853246446, ack 3038065703, win 65483, options [mss 65495,sackOK,TS val 2547077140 ecr 2547077140,nop,wscale 7], length 0
0x0000: 4500 003c 0000 4000 4006 4c4a c0a8 b690
0x0010: c0a8 b690 270f a0f2 aa11 15ee b515 3427
0x0020: a012 ffcb eea0 0000 0204 ffd7 0402 080a
0x0030: 97d1 5014 97d1 5014 0103 0307
IP 192.168.182.144.41202 > 192.168.182.144.9999: Flags [.], ack 1, win 512, options [nop,nop,TS val 2547077140 ecr 2547077140], length 0
0x0000: 4500 0034 dd64 4000 4006 6eed c0a8 b690
0x0010: c0a8 b690 a0f2 270f b515 3427 aa11 15ef
0x0020: 8010 0200 ee98 0000 0101 080a 97d1 5014
0x0030: 97d1 5014
qz@ubuntu:~$ sudo tcpdump -i lo -nt 'src 192.168.182.144' and 'dst 192.168.182.144' -S -nn -x
[sudo] password for qz:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
IP 192.168.182.144.60294 > 192.168.182.144.9999: Flags [S], seq 2529040303, win 65495, options [mss 65495,sackOK,TS val 2548439728 ecr 0,nop,wscale 7], length 0
0x0000: 4500 003c 5f5e 4000 4006 eceb c0a8 b690
0x0010: c0a8 b690 eb86 270f 96be 17af 0000 0000
0x0020: a002 ffd7 eea0 0000 0204 ffd7 0402 080a
0x0030: 97e6 1ab0 0000 0000 0103 0307
IP 192.168.182.144.9999 > 192.168.182.144.60294: Flags [S.], seq 2198379132, ack 2529040304, win 65483, options [mss 65495,sackOK,TS val 2548439728 ecr 2548439728,nop,wscale 7], length 0
0x0000: 4500 003c 0000 4000 4006 4c4a c0a8 b690
0x0010: c0a8 b690 270f eb86 8308 9a7c 96be 17b0
0x0020: a012 ffcb eea0 0000 0204 ffd7 0402 080a
0x0030: 97e6 1ab0 97e6 1ab0 0103 0307
IP 192.168.182.144.60294 > 192.168.182.144.9999: Flags [.], ack 2198379133, win 512, options [nop,nop,TS val 2548439728 ecr 2548439728], length 0
0x0000: 4500 0034 5f5f 4000 4006 ecf2 c0a8 b690
0x0010: c0a8 b690 eb86 270f 96be 17b0 8308 9a7d
0x0020: 8010 0200 ee98 0000 0101 080a 97e6 1ab0
0x0030: 97e6 1ab0
TCP的四次挥手
IP 192.168.182.144.32994 > 192.168.182.144.9999: Flags [F.], seq 18, ack 20, win 512, options [nop,nop,TS val 2553742425 ecr 2553741424], length 0
0x0000: 4500 0034 11d9 4000 4006 3a79 c0a8 b690
0x0010: c0a8 b690 80e2 270f 98ce 926d f0e0 8c9c
0x0020: 8011 0200 ee98 0000 0101 080a 9837 0459
0x0030: 9837 0070
IP 192.168.182.144.9999 > 192.168.182.144.32994: Flags [.], ack 19, win 512, options [nop,nop,TS val 2553742469 ecr 2553742425], length 0
0x0000: 4500 0034 4394 4000 4006 08be c0a8 b690
0x0010: c0a8 b690 270f 80e2 f0e0 8c9c 98ce 926e
0x0020: 8010 0200 ee98 0000 0101 080a 9837 0485
0x0030: 9837 0459
IP 192.168.182.144.9999 > 192.168.182.144.32994: Flags [F.], seq 20, ack 19, win 512, options [nop,nop,TS val 2553745427 ecr 2553742425], length 0
0x0000: 4500 0034 4395 4000 4006 08bd c0a8 b690
0x0010: c0a8 b690 270f 80e2 f0e0 8c9c 98ce 926e
0x0020: 8011 0200 ee98 0000 0101 080a 9837 1013
0x0030: 9837 0459
IP 192.168.182.144.32994 > 192.168.182.144.9999: Flags [.], ack 21, win 512, options [nop,nop,TS val 2553745427 ecr 2553745427], length 0
0x0000: 4500 0034 0000 4000 4006 4c52 c0a8 b690
0x0010: c0a8 b690 80e2 270f 98ce 926e f0e0 8c9d
0x0020: 8010 0200 e508 0000 0101 080a 9837 1013
0x0030: 9837 1013