建立一个可靠的TCP连接需要进行三次握手确认才建立的链接
1. 服务端准备好外来连接,调用socket,bind,listen,3个函数,被动打开
2. 客户端调用connect发起主动连接,TCP发送一个SYN(同步)分节,里面包含了要建立连接束数据,告诉服务器即将要建立连接
3. 服务器确认(ACK)客户端的SYN,同事自己也得发送SYN分节,包含服务器在该连接中发送的数据和初始序号,
4.客户端必须确认服务器的SYN
如下所示
客户 服务器
socket socket,bind,listen(被动打开)
accept (阻塞)
connect(阻塞) ------SYN J-(第一次握手)----------->
(主动打开)
connect 返回 <----SYNK , ACK J+1 -(第二次握手)------
accpet 返回
----------ACK(K+1)-----(第三次握手)----> read(阻塞)
为什么要三次握手而不能两次【转】
情况一: 现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
情况二: 那么第二次握手后服务器只向客户端发送ACK包,此时客户端与服务器端建立连接。在这种握手规则下: 如果发送网络阻塞,由于TCP/IP协议定时重传机制,B向A发送了两次SYN请求,分别是x1和x2,且因为阻塞原因,导致x1连接请求和x2连接请求的TCP窗口大小和数据报文长度不一致,如果最终x1达到A,x2丢失,此时A同B建立了x1的连接,这个时候,因为AB已经连接,B无法知道是请求x1还是请求x2同B连接,如果B默认是最近的请求x2同A建立了连接,此时B开始向A发送数据,数据报文长度为x2定义的长度,窗口大小为x2定义的大小,而A建立的连接是x1,其数据包长度大小为x1,TCP窗口大小为x1定义,这就会导致A处理数据时出错。
TCP连接终止的四次挥手
1,某个应用进程调用close,执行主动关闭,TCP发送一个FIN分节,表示数据发送完毕
2,接收到FIN的对端被动关闭,作为eof传递给接收端应用进程
3,一段时间后(因为要接受处理完其他数据)接收到这个和eof的应用进程close关闭它的套接字。发送一个FIN给员发送端
4,接收这个最终FIN的元发送端确认这个FIN
客户 服务器
(被动关闭)
close(主动关闭) --------FIN M------------> read返回0
<---ACK M+1 -------------
< ------FIN N ---------------
--------------------ACK N+1 ------------->
需四次挥手原因:由于TCP的半关闭特性,TCP连接时双全工(即数据在两个方向上能同时传递),因此,每个方向必须单独的进行关闭。这个原则就是:当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向上的连接。当一端收到一个FIN后,它必须通知应用层另一端已经终止了那个方向的数据传送。即收到一个FIN意味着在这一方向上没有数据流动了。