TCP是面向连接的协议。面向连接的运输层协议在源点和终点之间建立了一条虚路径。
同属于一个报文的所有报文段都沿着这条虚拟路径发送。为整个报文使用一条虚路径能够更容易地实施确认过程以及对损伤或丢失报文的重传。
在TCP中,面向连接的传输需要经过三个阶段: 连接建立、数据传输和连接终止
连接建立
TCP以全双工方式传送数据。当两台主机的两个TCP建立连接后,它们应当能够同时向对方发送报文段。也就是说,在任何数据传达之前,双方都必须对通信进行初始化,并得到对方的认可。
三次握手
在TCP中使用的连接建立过程称为三向握手(three-way handshaking)
在我们的例子中,一个称为客户的应用程序希望使用TCP作为运输层协议来和另一个称为服务器的应用程序建立连接。
这个过程从服务器开始。服务器程序告诉它的TCP字节已准备好接受连接。这个请求称为被动打开请求。虽然服务器的TCP已准备好接受来自世界上任何一个机器的连接,但是它自己并不能完成这个连接。
客户程序发出的请求称为主动打开。打算与某个开放的服务器进行连接的客户告诉它的TCP,自己需要连接到某个特定的服务器上。TCP现在可以开始进行如图的三次握手过程。
这个的阶段的三个步骤如下所示:
客户发送第一个报文段(SYN报文段),在这个报文段中只有SYN标志置为1.这个报文段的作用是同步序号。
在例子中,客户选择了一个随机数作为第一个序号,并把这个序号发送给服务器。这个序号称为初始序号(ISN)。(请注意这个报文段中不包括确认号,也没有定义窗口大小。只有当一个报文段中包含了确认时,定义窗口大小才有意义。)
SYN报文段是一个控制报文段,它不携带任何数据,但是,它消耗了一个序号。当数据传送开始时,序号就应该加1.
SYN报文段不携带任何数据,但是它要消耗一个序号服务器发送第二个报文段,即SYN+ACK报文段,其中的两个标志(SYN和ACK)置为1.这个报文段有两个目的。首先,它是另一个方向上通信的SYN报文段。服务器使用这个报文段来同步它的初始序号,以便从服务器向客户发送字节。其次,服务器还通过ACK标志来确认已收到来自客户端的SYN报文段,同时给出期望客户端收到的下一个序号。因为这个报文段包含了确认,所以它还需要定义接收窗口大小,即rwnd(由客户端使用)
SYN+ACK报文段不携带数据,但要消耗一个序号客户发送第三个报文段。这仅仅是一个ACK报文段。它使用ACK标志和确认号字段来确认收到了第二个报文段。
请注意这个报文段的序号和SYN报文段使用的序号一样。也就是说,这个ACK报文段不消耗任何序号。客户还必须定义服务器的窗口大小。在某些实现中,连接阶段的第三个报文段可以携带客户的第一个数据块。在这种情况下,第三个报文段必须有一个新的序号来表示数据中的第一个字节的编号。
ACK报文段如果不携带数据就不消耗序号。
同时打开
当两个进程都发出主动打开请求时,可能会发生一种罕见的情况。此时,两个TCP都向对方发送SYN+ACK报文段,然后在它们之间建立一条连接。之后的文章中会说明这一情况
SYN洪泛攻击
TCP中使用的连接建立过程很容易碰到一个严重的安全问题,称为SYN洪泛攻击(SYN flooding attack)。当一个或多个恶意的攻击者向某台服务器发送大量的SYN报文段,并通过伪造报文段中的源IP地址来假装每一个报文段来自不同的客户时,这个问题就发生了。服务器认为这些客户发来了主动打开的请求,于是就分配必要的资源,如创建传送控制块(TCB)表,并设置一些计时器。然后TCP的服务器向这些假冒的客户发送SYN+ACK报文段,而这些报文段都丢失了。但是,在服务器等待握手的第三步的这段时间里,大量的资源被占而没有利用。如果在很短的时间内,SYN报文段的数量很大,服务器最终会因资源耗尽而不能接受来自合法客户的连接请求。
TCP的某些实现采取了一些策略来减轻SYN攻击的影响,有些实现强制限定在指定时间内的连接请求次数。有些则把来自不希望的源地址的数据报过滤掉。