TCP/IP:是一个协议族,其中包含应用层、传输层、网络层、数据链路层的各种协议。
其中,
在网络层有:IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。
在传输层有:TCP协议和UDP协议。
在应用层有:HTTP、FTP、TELNET、SMTP、DNS等协议。
所以说,HTTP本身就是一个协议,是从web服务器传输超文本到本地浏览器的传送协议。
而Socket是在应用层与传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。
TCP是面向连接的、传输可靠(保证数据正确性且保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。
建立一个TCP连接是需要“三次握手”,即交换三个分组。
三次握手的目的是连接服务器的指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换TCP窗口大小信息。在Socket编程中,客户端执行connect()时,将触发三次握手。
首先了解一下三次握手建立连接中的两个序号和两个标志位:
seq(Sequence Number),序列号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记;
ack,确认序列号,占32位,只有ACK标志位为1,确认序列号才有效,ack = seq+1;
SYN(Synchronous),同步标志,发起一个连接;
ACK(Acknowledgement),确认标志,确认序号有效;
大致流程如下:
1.客户端向服务端发送一个SYN=1的包指明客户端打算连接的服务器的端口,以及初始序列号J,保存在包头的序列号seq字段里,及seq=J;
此时Client进入阻塞等待状态,即同步已发送。
2.服务器收到客户端发来的连接请求后,向客户端发回确认包SYN=1,ACK=1,确认序列号ack=J+1来确认并应答,同时为自己初始一个序列号K;
此时Server进入同步已收到状态。
3.客户端收到服务器的确认后,还需向服务器给出确认ACK=1,确认序列号ack=K+1,并设置发送这次请求的序列号为J+1。
此时client已经建立连接。
当服务器收到客户端的确认时,Server也会进入EXTABLELISHED状态。
为什么客户端还要发送一次确认呢?这主要是为了防止已失效的连接请求报文段突然有传送到了Server,因而产生错误。
所谓“已失效的连接请求报文段”是这样产生的。考虑一种正常情况,Client发出连接请求,但因连接请求报文丢失而未收到确认。于是Client在重传一次连接请求,后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了Server。没有“已失效的连接请求报文段”。
现假定出现一种异常情况,即Client发出的第一个连接请求报文段并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放后的某个时间才到达Server。本来这是一个早已失效的报文段,但Server收到此失效的连接请求报文段后,就误认为是Client又发出一次新的连接请求。于是就向Client发出确认报文段,统一建立连接。假定不采用三次握手,那么只要Server发出确认,新的连接久建立了。
由于现在Client并没有发出建立连接的请求,因此不会理睬Server的确认,也不会向Server发送数据。但Server却以为新的运输连接已经建立了,并一直等待Client发来数据。Server的许多资源就这样白白浪费了。
采用三次握手的办法可以防止上述现象的发生。例如在刚才的情况下,Client不会向Server的确认发出确认。Server由于收不到确认,就知道Client并没有要求建立连接。
断开TCP连接是需要“四次挥手”。
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭。
其中,需了解一下FIN,断开标志,释放一个连接;
大致流程如下:
数据传输结束后,通信的双方都可释放连接。现在Client和Server都处于ESTABLISHED状态。
1.Client的应用进程先向TCP发出连接释放报文段,主动关闭TCP连接。Client把连接释放报文段终止控制位FIN=1,序号seq=u--它等于前面已传送过的数据的最后一个字节的序号加1。这时Server进入FIN-WAIT-1(终止等待1)状态,等待Server的确认。
2.Server收到连接释放报文段后即发出确认(发出的不是连接释放报文段),确认号ack=u+1,而这个报文段自己的序号是u--等于Server前面已传送过的数据的最后一个字节的序号加1。然后Server就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时通知高层应用进程,因而从Client到Server这个方向的连接释放了,这时的TCP连接处于半关闭状态--即Client已经没有数据要发送了,但Server若发送数据,Client仍要接受。也就是说,从Server到Client这个方向的连接并未关闭。这个状态可以会持续一些时间。
Client收到Server的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待Server发出的连接释放报文段。
3.若Server已经没有要向Client发送的数据,其应用进程就通知TCP释放连接。这时Server发出的连接释放报文段必须使用FIN=1。现假定Server的序号为w(在半封闭状态Server可能又发送了一些数据)。Server还必须重复上次已发送过的确认号ack=u+1。这时Server金土LAST-WAIT状态,等待Client的确认。
4.在Client收到Server的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置为1,确认号ack=w+1,而自己的序号是seq=u+1(前面的FIN报文消耗了1个序号)。然后进入TIME-WAIT状态。请注意,现在TCP连接还没释放掉。必须再经过2MSL后,Client才进入到CLOSED状态。MSL叫最长报文段寿命,一般为2分钟。
当Server收到Client发出的确认,就进入CLOSED状态。由此可见Server结束TCP连接的时间要比Client早一些。等到2MSL结束后Client也进入CLOSED状态,至此完成了TCP四次挥手断开连接的全过程。