一.概述
传输层位于七层模型的第四层,用户功能里面的最底层,面向通信部分的最高层
传输层工作的位置是终端设备,网络中的路由器没有传输层
传输层负责管理端到端的通信连接
进程与进程的通信
使用端口号(Port)来标记不同的网络进程
端口(Port)使用16比特位表示(0~65535)
UDP协议
UDP(User Datagram Protocol)用户数据报协议
UDP协议的位置
UDP协议的首部
源端口号:源机器使用网络的进程
目的端口号:目的机器正在使用的网络进程
UDP长度:UDP数据报的长度
校验和:检测UDP数据报在传输过程中是否出错
UDP特点
UPD是无连接协议
UDP不能保证可靠的交付数据(想发就发,无法保证数据在网络中是否丢失)
UDP是面向报文传输的(面向报文:应用层传来的数据报)
UDP没有拥塞控制(把网络比做一条公路,UDP不管网络是否发生拥塞,都会尽量把数据交付出去给网络)
UDP的首部开销很小(首部开销:源端口号,目的端口号,数据长度,校验和这四部分)
TCP协议
TCP(Transmission Control Protocol)传输控制协议
TCP协议的特点
TCP是面向连接的协议
TCP的一个连接有两端(点对点通信)
TCP提供可靠的传输服务
TCP协议提供全双工的通信(全双工:两端可以同时发出数据和接收数据)
TCP是面向字节流的协议(UDP是面向数据报的协议,TCP面向字节流,字节流是流入进程和流出进程的字节序列,TCP不把应用层的数据看作一整块,而是看作一系列的字节流,可能会对用户数据进行拆分和合并进行发送)
可靠传输的基本原理
停止等待协议,连续ARQ协议
停止等待协议
发送方发送消息到接收方,接收方接收到消息后生成确认消息,发送给发送方,发送方收到确认消息后再生成消息2发送给接收方。在这几次消息发送和接收过程中,双方都要等待对方的消息接收到之后再发送新的消息。发送方发送消息后就停止生成新的消息,等待接收方的确认消息到达发送方后再生成第二个消息。
连续ARQ协议
//待补充
滑动窗口协议
//待补充
TCP报文头部
其他部分待补充...
TCP标记
TCP连接的建立
设主机B接收方运行一个服务器进程,它先发出一个被动打开命令,告诉它的TCP要准备接收客户进程的连续请求,然后服务进程就处于听的状态。不断检测是否有客户进程发起连续请求,如有,作出响应。设主机A作为发送方,它先向自己的TCP发出主动打开的命令,表明要向某个IP地址的某个端口建立运输连接。客户端发送的第一个数据包是一个请求报文段,报文内容包括同步位SYN=1,另一个是初始序号seq=x.TCP规定,SYN=1的报文不能携带数据,但是消耗一个序列号。客户端发送了这个报文之后,进入SYN-SENT(同步已发送)状态。
服务端已收到这个数据包之后,知道客户端请求连接,如果当前有资源,可以同意连接,则给客户端发送确认报文。确认报文的内容包括SYN=1(没有变化),seq=y(服务端的序列号),新增ACK=1,ack=x+1(客户端序列号+1)这里的SYN=1,所以报文不能携带数据,同样消耗了服务端的一个序列号,然后服务端进入了SYN-RCVD(同步收到)状态。
客户端收到服务端的确认报文后,还需要给服务端发送一个确认报文。这个报文的内容是ACK=1,seq=x+1,ack=y+1.这里没有了SYN字段,可以携带数据。客户端确认报文发送出去之后,客户端进入ESTABLISKED(已建立连接)
服务端接收到这个数据包之后,也进入了ESTABLISHED(已建立连接)状态。
为什么发送方要发出第三个确认报文呢?
首先建立连接,必须要有两次握手吧,客户端主动一次,告知服务端,我想和你建立连接,然后看服务端是否同意。然后如果服务端同意的话,得给一个回复,然后开始等待客户端的数据包,这就是两次握手。如果这个时候就建立连接,客户端开始给服务端发送数据包,在正常情况下没啥问题。但是由于网络并不是100%任何时候都稳定,一旦因为某些原因导致服务端发送给客户端的确认报文丢失,那这个时候客户端收不到确认数据包,会误以为服务端不同意连接,不会给服务端发送数据包,但是这时候服务端已经在等待了。这样的差错会导致服务端一直处于等待状态,浪费资源。
而三次握手的话,客户端在确认服务端同意之后再发一次数据包给服务端,告知服务端,不管怎么样我都会给你发送数据包的。因为TCP协议中,建立连接之后,每一次发送数据包客户端都会等待服务端的确认信息,如果收不到某一个数据包的确认信息,客户端就会重发这个数据包。这样就不会发生差错了。
已经失效的链接请求报文传送到对方引起错误
TCP连接的释放
当TCP连接需要释放时,客户端和服务端都是处于ESTABLISHED(已建立连接)状态。此时,客户端数据发送完毕,想要结束连接,主动发出连接释放请求数据包。这个数据包内容:Fin=1,seq=u(这个u是这个数据包之前一个数据包的序列号+1),客户端进入FIN-WAIT-1(终止等待1)状态,不再发送数据包,等待服务端的确认。
服务端接收到释放数据包之后发出确认,确认包中内容:确认号ack=u+1,序列号seq=v(这个v是服务端上一个发送的数据包的序列号+1),另一个是ACK=1。然后服务端进入CLOSE-WAIT(关闭等待)。这个时候客户端到服务端的连接已经结束了。但是TCP是全双工通信,因为这个时候是客户端主动发起的结束,在服务端这边可能还存在着数据没有完全发送给客户端,所以服务端到客户端仍然没有结束。客户端已经不能在发送数据了,如果服务端还有数据发送过来,客户端仍然要接收。
客户端收到服务端的确认之后,进入FIN-2(终止等待2)状态,等待服务端发送服务端发器的连接释放数据包。这时候服务端可能还有一些数据包要发送给客户端,客户端一一接收。最后,没有数据要发送了之后,服务端发送连接释放数据包,这个数据包内容:FIN=1,ACK=1,seq=w(因为在服务端回复客户端的连接请求(数据包的序列号是v)之后,可能仍然有其他数据包要发送,所以这里的w不一定是v+1),ack=u+1(确认号和上次回复客户端的请求释放连接的确认号一样)。接着服务端进入LAST-ACK(最后确认状态),等待客户端的确认。
客户端收到服务端的连接释放数据包之后,发出一个确认数据包,内容:ACK=1,seq=u+1,ack = w+1。然后客户端进入TIME-WAIT(时间等待)状态。这个时候TCP还没有释放。仍需要经过时间等待计时器设置的时间2MSL后,客户端才会进入CLOSED状态。MSL称为最长报文段寿命。RFC793建议把这个值设为2分钟,那这样的话,在客户端收到服务端的连接释放数据包之后,需要等待4分钟才能进入CLOSED状态。这显然时间太长了,不过这个值设为2分钟也只是建议,还是可以设置适合的时间的。最后服务端收到这个客户端的确认包之后就进入了CLOSED状态。显然,服务端一般先于客户端进入关闭状态。
之所以客户端需要等待2MSL时间才完全结束TCP连接,原因有两个:
一、为了保证客户端发送的最后一个确认包能正确到达服务端。因为如果由于网络原因丢失的话,服务端会重新发送连接释放数据包,在等待过程中,如果真的发生这种情况就可以得到处理。客户端每接收到一次服务端发送来的接释放数据包都会重新设置时间等待计时器,然后等待2MSL时间才完全结束TCP连接。
二、等待才2MSL时间完全结束TCP连接,可以避免再次开启TCP连接的时候收到上一次TCP连接存在网络中的数据包,显然这样的数据包不是属于本次连接的,是无效的数据包。
之所以需要四次握手来释放连接,TCP是全双工通信,支持两个方向通信,所以结束的时候,每个方向为了确保数据都能完全从一端到达另一端,所以结束的时候,一端发起结束申请数据包,另一端都要发送确认数据包。两个方向要分开结束,每次结束需要两次握手,所以最终TCP的结束需要4次握手。