@chenxuxiong
2016-06-04T17:00:03.000000Z
字数 2502
阅读 703
TCP报文结构、三次握手、四次挥手
计算机网络
1.TCP报文结构

- 源端口、目的端口:16位长。标识出远端和本地的端口号。
顺序号:32位长。表明了发送的数据报的顺序。
确认号:32位长。希望收到的下一个数据报的序列号。
ACK确认位:ACK位置1表明确认号是合法的。如果ACK为0,那么数据报不包含确认信息,确认字段被省略。
- PSH:表示是带有PUSH标志的数据。接收方因此请求数据报一到便可送往应用程序而不必等到缓冲区装满时才传送。
- SYN同步位:用于建立连接。
- FIN释放连接位:用于释放连接。
- RST:用于复位由于主机崩溃或其它原因而出现的错误的连接。还可以用于拒绝非法的数据报或拒绝连接请求。
- 窗口大小:16位长。窗口大小字段表示在确认了字节之后还可以发送多少个字节。
- 校验和:16位长。是为了确保高可靠性而设置的。它校验头部、数据和伪TCP头部之和。
- 可选项:0个或多个32位字。包括最大TCP载荷,窗口比例、选择重发数据报等选项。
- TCP协议数据报头DE 头长:4位长。表明TCP头中包含多少个32位字。
接下来的6位未用。
最大TCP载荷:允许每台主机设定其能够接受的最大的TCP载荷能力。在建立连接期间,双方均声明其最大载荷能力,并选取其中较小的作为标准。如果一台主机未使用该选项,那么其载荷能力缺省设置为536字节。
窗口比例:允许发送方和接收方商定一个合适的窗口比例因子。这一因子使滑动窗口最大能够达到232字节。
TCP协议数据报头选择重发数据报:这个选项允许接收方请求发送指定的一个或多个数据报。
2.tcp三次握手
1、三次握手讲解
- 根据图解

- (1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
2、如果客户端不断的发送请求连接会怎样?
- 只要能建立连接,将数据发送到发送缓冲区中就会成功返回,也就是发送缓冲区没满就会返回成功
- 服务端的接收缓冲是否已满客户端是不知道的,所以当缓存区满了的时候就会请求连接失败。
- 我们可以建立长连接来避免这种不断发生请求连接。
tcp如何保持长连接?
- 自己实现心跳包,或者开启Keepalive(存活定时器)功能:
- 当一个连接“一段时间”没有数据通讯时,一方会发出一个心跳包(Keep Alive包),如果对方有回包则表明当前连接有效,继续监控。
- 这个“一段时间”可以设置。CURLOPT_TCP_KEEPIDLE是空闲多久发送一个心跳包,CURLOPT_TCP_KEEPINTVL是心跳包间隔多久发一个。
- Keepalive(存活定时器):短连接在数据包发送完成后就会自己断开,而长连接在发包完毕后,会在一定的时间内保持连接。
- 默认的Keepalive超时2小时,探测次数为5次。它的功效和用户自己实现的心跳机制是一样的。
3、为什么是三次握手而不是两次?
- 采用三次握手是为了防止失效的连接请求报文段突然又传送到服务端,因而产生错误。
- 场景:客户端发出的连接请求没有收到服务端的确认,于是经过一段时间后,客户端又重新向服务端发送连接请求,且建立成功,顺序完成数据传输。
- 考虑这样一种特殊情况,服务端第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到服务端,服务端以为是客户端又发起的新连接,于是服务端同意连接,并向客户端发回确认,但是此时客户端根本不会理会,服务端就一直在等待客户端发送数据,导致服务端的资源浪费。
4、那两次服务端会怎样?客户端会怎样?
- 这时候服务端会发送确认连接,如果这请求已经失效了,客户端是不会理睬的,服务端是不知道的。
- 但是服务端仍然会一直等待客户端发送数据,而造成资源浪费。
- 场景:如上。
- 如何判断失效? 客户端连接请求被阻塞,客户端确认连接超时,重写发送请求,认定前一次的连接请求失效。
5、怎样知道是恶意连接?
- 我们可以设定一个暗号,在建立连接时要验证暗号,就像输入账号名和密码一样。
- 如果错误超过一定次数,就设定一个计时器,来对对方的连接做直接拒绝处理。
3.tcp四次挥手
1、讲解
- 图解

- (1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
2、为什么建立连接是三次握手,关闭连接是四次挥手?
- 服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
- 而收到关闭连接请求时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN**一般**都会分开发送。