TCP/IP簇是网络通信时经常用的到一系列协议,包含TCP,UDP,IP,FTP,HTTP,ICMP,SMTP,Socket等都属于TCP/IP,作为一名后台开发的码农,了解一些底层原理有助于理解和处理很多问题。这些东西一篇博客是讲不完的,讲到哪里是哪里。

首先介绍TCP协议:

TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。流就是指不间断的数据结构,可以理解为水管里源源不断的水流。TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个响应的确认包(ACK),如果发送端实体在合理的往返时延内为收到确认,那么对应的数据将会被重传。
上面这段话信息量很大,需要仔细读几遍。

TCP的连接需要经过三次握手,流程如下:

1.客户端发送SYN包给服务器,进入SYN_SEND状态
2.服务器端收到SYN报文,回应一个SYN+ACK报文给客户端,进入SYN_RECV状态
3.客户端收到服务器端的SYN报文,回应一个ACK报文,进入Established状态。
整个连接过程结束,开始通信。

连接终止需要四次握手,流程如下:

1.某个应用首先调用Close,称该端执行主动关闭,该端的TCP于是发送一个FIN分节,表示数据发送完毕。
2.接收到FIN的对端执行被动关闭,这个FIN由TCP确认。
3.一段时间后,接收到这个文件结束符的应用进程将调用close关闭他的套接字。这导致他的TCP也发送一个FIN。
4.接收第二个FIN的原发送端TCP确认接收第二个FIN,连接关闭。

无论是客户还是服务器,任何一端都可以执行主动关闭。通常情况是,客户执行主动关闭,但是某些协议,例如,HTTP/1.0却由服务器执行主动关闭。

为什么TCP是三次握手,而不是两次或四次?

这个问题我在面试腾讯的时候没答出来,但是面试官说没关系,需要工作一段时间之后才能理解。解答如下:
TCP的最大特点就是可靠,可靠,可靠,但是传输效率又不能太低,所以三次握手刚刚可以满足以上两个特点。

TCP连接的一方A,由操作系统动态随机选取一个32位长的序列号(Initial Sequence Number),假设A的初始序列号为1000,以该序列号为原点,对自己将要发送的每个字节的数据进行编号,1001,1002,1003…,并把自己的初始序列号ISN告诉B,让B有一个思想准备,什么样编号的数据是合法的,什么编号是非法的,比如编号900就是非法的,同时B还可以对A每一个编号的字节数据进行确认。如果A收到B确认编号为2001,则意味着字节编号为,共1000个字节已经安全到达。

B端向A端发送消息也同理。

总结起来就是:TCP握手的实质,也是握手的主要目标, 就是通信双方数据原点的序列号!
假如为四次握手,则流程如下
前提条件:A向B发送连接请求
1.A发送SYN包,加上A的初始序列号ISN initial sequence number
2.B收到A的SYN包,并记录A的ISN,命名B的ACK sequence number
3.B发送同步信号SYN,加上B的初始化序列号
4.A收到B的同步信号,并记录B的ISN到本地,明明A的ACK sequence number

很显然,二三两步可以合在一起,因为记录A的序列号和发送自己的序列号这两个操作并不冲突,而减少一次消息传递可以提升效率。

假如为两次握手:
1.A发送SYN加 A的ISN
2.B发送A一个SYN包加自己的ISN,并记录A的ISN

此时问题出现了,B并不知道A有没有成功记录到自己ISN,假如A端因为某些原因没有接收到这个包,那么以后的传输就会出问题,因为不知道从哪个位置开始。

关于ACK和SYN:
SYN和ACK是有些不同的,SYN包被设计为了一个占用一个字节的编号,也就是说,SYN是含有数据的,如果SYN在传输中丢失了,那么依照TCP可靠传输的规则,在规定时间内没有收到ACK包,会再次发送。
而ACK没有数据,所以如果ACK丢失,因为没有数据,所以不会重发ACK包,而是由发送端重发SYN包

总结起来就是:

  1. 发送端发的SYN包丢失,发送端重发SYN包。
  2. 接收端的用来回应发送端的ACK包丢失,发送端重新发送SYN,直至接收到ACK。
Last modification:May 23rd, 2019 at 09:28 am
如果觉得我的文章对你有用,请随意赞赏