浅探网络1---tcp协议详解

TCP协议是网络多层协议中运输层的最重要的协议之一,运输层是两台主机的进程之间的通信。除了TCP还有一个是UDP协议(用户数据包协议)

TCP全称是Transmission Control Protocol,意思是传输控制协议

一、TCP简介

1.TCP协议两个对等运输实体之间进行传送的数据单位是:TCP报文段

2.TCP提供的是面向连接的服务,在传送数据之前必须建立连接,数据传送完成之后需要关闭连接,TCP只可点对点,不可广播或多播,TCP连接是可靠的运输服务。

3.TCP的工作方式类似于打电话,打电话之前需要先拨号(号码就是连接的IP+端口号)连接,通话结束之后关闭连接

4.TCP提供可靠交付,即TCP传输的数据无差错、不丢失、不重复且有序

5.TCP支持全双工通信,即通信双方可随时发送数据,发送方发送完数据会先放到发送缓存中,发送方发送完毕就可以干别的事去了,TCP会在合适的时机将数据发送给接受方,接收方接收到数据会先把数据放到接收缓存中,应用程序会在合适的时机在缓存中获取数据。

6.TCP是面向字节流的,流入到进程或从进程中流出的是字节序列。而发送时和接收时除了传输的业务数据,可能还会额外加一些字节数据,用于发送方和接收方处理。比如在微信聊天中需要提醒接收方会添加@XXX,而接收方只需要接收有用信息,@信息是和业务无关的。

7.TCP连接的双方不是两个主机、不是两个IP地址、不是两个应用程序、而是两个套接字,每个套接字socket=(IP地址:端口号),每一个TCP连接必须有唯一的两个套接字,即TCP连接={套接字1,套接字2}={(IP1,port1),(IP2,port2)}

二、TCP三次握手和四次挥手

TCP是面向连接的协议,所以协议的基础就是需要有连接,而发起连接的一方可以称为客户端,等待连接的一方可以称为服务端。而TCP建立连接的过程称为握手,每次握手客户端和服务器之前需要交换三个报文段,因此也叫做“三次握手”。

在RFC973(TCP标准文档)中使用的名称是three way handshake,这里的handshake没有用复数,所以三次握手不太准确,应该叫三次报文握手,因为人与人之间握手的意思就是已经连接上了,手上摇晃了三次之后才最终握上,所以准确点说应该是握手成功了一次。但是三次握手的说法比较普遍,所以本文也叫做三次握手。在理解TCP连接之前,先来了解一些常量的含义

SYN:发起一个连接,同步位

FIN:关闭一个连接

ACK:确认连接有效

RST:重置连接

seq:序号,每次发送一次数据,seq=上一个seq+1

ack:应答序号

上图是TCP连接三次握手示意图

第一次握手:A向B发送连接请求报文,同步完syn=1,初始化序号seq=X,TCP协议规定syn=1的报文不允许携带数据,所以SYN=1即表示发起连接请求,当A发送第一次握手之后,A就进入了SYN-SENT状态,表示同步已发送

第二次握手:B接收到A发送的请求报文,如果同意连接,则向A发送确认。发送同步报文段SYN=1,seq=y,确认报文段ACK=1,确认序号ack=x+1。此时服务端进入SYN-RCVD状态,表示同步已接收

第三次握手:A接收到B的确认报文,再向B发起确认,设置ACK=1,确认序号seq=x+1,ack=y+1,此时TCP连接完成,双方都进入ESTAB-LISHED状态,表示连接以建立。

那么为什么需要三次,而不是两次就行,还需要最后再发送一次确认呢?或者说如果没有最后一次确认会发送什么?看看下面这种情况:

A发出连接请求,但是在网络中长时间滞留了而没有发送到B,此时由于A久久没有接收到B发送过来的确认请求,所以A就将连接释放了,在A释放了连接之后B又接收到了A发送过来迟到的连接请求,由于B不知道此时A已经释放了连接了,所以B认为是有效的连接,

此时B向A发送确认,同意建立连接(如果只要两次握手,那么此时B就已经进入了ESTAB-EISHED状态),此时A已经释放了连接,所以接收到B的确认请求也不会理睬,但是B还是认为连接有效而一直等待着A发送数据,就会导致B持有无效的连接而浪费资源。

而如果采用三次握手,那么B在发送完确认之后,只会进入到SYN-RCVD状态,并不会建立连接的等待数据的发送,除非A再次发送了确认请求。

TCP连接是双向的,所以TCP连接的释放是双方都可以发起的,以A为例发起释放连接,需要经过四次挥手,过程如下图示:

在连接释放之前,A和B都是出于ESTAB-LISHED状态,且可以数据传输,此时A开始进行关闭

第一次挥手:A向B发送关闭连接请求,FIN=1,seq=u(u的值等于数据传输的最后一个请求的序号+1),此时A进入FIN-WAIT-1状态,等待B确认。TCP规定FIN报文不可携带数据

第二次挥手:B接收到A的关闭连接请求,并发出关闭确认,ACK=1,seq=v(v的值等于B传送的最后一个字节的序号+1),ack=u+1,然后B进入CLOSE-WAIT(等待关闭)状态,且需要通知应用进程A需要关闭连接,不再发送数据过来了。

此时TCP连接进入半关闭状态,也就是A-B的连接已经关闭,B-A的连接还没有关闭,但A接收到B的关闭确认之后进入FIN-WAIT-2状态,等待B发送关闭连接报文

第三次挥手:若B没有数据再发送给A,则向A发送关闭连接报文,FIN=1,ACK=1,seq=w(w的值等于B传送的最后一个字节的序号+1),ack=u+1,并且B进入LAST-ACK(最后确认)状态,等待A的确认

第四次挥手:A收到B的关闭连接报文之后,再向B发送一次确认报文,ACK=1,seq=u+1,ack=w+1,并且进入到TIME-WAIT(时间等待)状态,需要等待2MSL时间之后才会进入到CLOSED状态,而B接收到关闭确认报文之后就直接进入CLOSED(关闭)状态。

这里有两个问题,一是为什么需要有四次握手,而不是两次或三次?二是A在发送关闭确认请求之后,为什么还需要等待2MSL长时间才进入CLOSED状态?(MSL一般是2分钟,2MSL就是4分钟)

回答一:和三次握手一样,挥手只用两次肯定是不够用的,那三次为什么也不够呢,因为第一次关闭连接是A向B发起的,表示A不会发送数据给B了,但是此时可能B还有数据需要传送给A,如果B在数据还没有传输完成就通知A,则数据就会丢失;如果B在数据传输完成之后再通知A,那么此时可能已经超时了,导致A以为发起的关闭连接失效了就会重新发送多次的关闭连接。而四次挥手比三次握手多的一次报文是B向A发送的关闭连接请求,表示B也已经不会发送数据给A了,这样就确保了双方都没有数据发送了,且都对对方的关闭连接做了关闭确认。

回答二:设置TIME-WAIT状态等待2MSL主要有两个原因:

原因1:防止第四次挥手丢失,如果A在发送第四次挥手报文之后马上进入CLOSED状态,而B有可能没有接收到这个确认报文,就会一直处于LAST-ACK状态,在超时之后B就会重发关闭连接报文,而此时A已经进入CLOSED状态了,就会导致B无法进入CLOSED状态。

而设置了TIME-WAIT状态之后,A会等待2MSL时间,如果B重发了FIN+ACK报文,A还是可以接收到并且发出关闭确认报文,直到B进入CLOSED状态。

原因2:确保A最后发送的报文在网络中消失,MSL表示报文的最长寿命,达到时间报文就会失效,所以A等到2MSL时间之后,报文无论是否被B接收到肯定是会失效,这样就确保了此报文不会影响到下一个新的连接。而如果没有TIME-WAIT状态,而是A直接进入CLOSED状态,然后A又再次和B通过三次握手建立了连接,此时A最后发送的关闭确认报文可能还在网络中传输,就会出现旧的报文段出现的新的连接中。

猜你喜欢

转载自www.cnblogs.com/jackion5/p/10673906.html