如同人与人之间相互交流是需要遵循一定的规则(如语言)一样,计算机之间能够进行相互通信是因为它们都共同遵守一定的规则,即网络协议。
OSI参考模型和TCP/IP模型在不同的层次中有许多不同的网络协议,如图所示:
我们今天主要讨论的是传输层的协议,即考虑应用程序之间的逻辑通信。简单来说就是数据该如何发送给其他机器;
UDP(User Datagram Protocol):用户数据报协议;UDP是面向无连接的通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
UDP是面向报文传递数据的;在UDP传输过程中,分别为发送端和接收端;
发送端使用UDP发送数据时,首先将其包裹成一个UDP报文(包含数据与首部格式)通过网络将其发送给接收端;接受端接收到UDP报文后,首先去掉其首部,将数据部分交给应用程序进行解析;
需要注意的是,UDP不保证数据传递的可靠性,在传递过程中可能出现丢包等情况,另外,即使接收方不存在报文依旧被发送出去(丢包)。但正是因为UDP不需要花费额外的资源来建立可靠的连接,因此UDP传输速度快,资源消耗小;
一个完整的UDP报文包含首部和**载荷(数据)**两部分,首部由 4 个 16 位长(2 字节)的字段,共8个字节组成,分别说明该报文的源端口、目的端口、报文长度和校验值。
UDP 报文中每个字段的含义如下:
由于使用UDP协议消耗资源小,通信效率高;因此一般用于实时性要求比较高的场合如:音频、视频的传输等;例如视频会议都使用UDP协议,如果出现了网络丢包情况也只是造成卡帧现象,对整体影响不大
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
TCP(Transmission Control Protocol):传输控制协议;TCP协议是面向连接的通信协议;即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
在TCP连接中必须要明确客户端(发送端)与服务器端(接收端),由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”;
一个完整的TCP报文同样也是由首部和数据载荷组成;TCP的全部功能都体现在它首部中各字段的作用。
序号占4个字节,32个比特位,取值范围
2^32-1
,序号增加到最后一个时,下一个序列号又回到0;
确认号和序号一样,占4个字节,32个比特位,取值范围
2^32-1
,确认号增加到最后一个时,下一个确认号又回到0;
A向B发送数据:
B向A发送数据:
若确认号=n,则表明,序号n-1为止的所有数据都已正确接收,期望接收序号为n以及之后的数据;
本次的序列号 = 上次的确认号
本次的确认号 = 上次的序列号 + 数据载荷的长度
如图:
由于TCP是基于可靠通信的,在发送数据之前必须建立可靠的连接;TCP建立连接的过程分为三个步骤,我们称为"三次握手";
简单的过程如下图所示:
我们结合TCP报文原理来具体分析一下三次握手的详细流程:
原理图如下:
首先客户端使用向服务端发送TCP连接请求(此报文不携带载荷,只有首部),本次请求中SYN标记为1,表明本次是一个连接请求。序号标记为x,作为本次TCP连接的客户端起始序号值;
Tips:在TCP协议中规定,SYN标记为1的报文不可以携带数据,但还是要消耗掉一个序号
服务端接收到客户端的请求后,如果确定建立连接,则向客户端发送一个确认报文。该报文SYN标记为1,表明本次是一个连接请求。ACK标记为1,表明本次是一个确认请求。
综合本次请求的含义为:连接确认请求,即服务端收到客户端请求之后,来与客户端建立连接,表明同意与客户端建立本次TCP连接;
本次请求序号标记为y,作为本次TCP连接服务端的起始序号值。确认号为x+1,这是对上一次请求初始序号x的确认。
客户端再次向服务端发送确认报文,该报文中ACK标记为1,表明本次是一个确认报文。
本次确认报文的序号为x+1,这是因为第一次TCP报文的序号为x,并且不携带数据,因此本次序号为x+1
本次确认报文的确认号为y+1,这是针对服务端请求初始序号y的确认。
在三次握手中,为什么客户端最后还需要发送一个确认报文呢?难道在服务端响应确认报文之后不能确定TCP连接已经建立成功吗?
即:为什么要三次握手而不是"两次握手"呢?
我们观察下图:
①客户端发送TCP连接请求到服务端,想要建立连接,但由于本次请求超时了
②客户端再次发送一个新的TCP连接请求到服务端
③服务端接收到客户端刚刚发送的TCP连接请求,开始做出回应
④客户端接收到服务端的回应,连接建立成功
⑤过了一段时间后,客户端像服务端发送断开连接请求(进入四次挥手过程,暂时不讨论)
⑥服务端与客户端断开连接后,突然收到之前客户端发送的超时请求,但服务端还以为是客户端刚发送的连接请求,因此对该请求进行确认
⑦由于是"两次握手",并不需要等到客户端对本次连接做出回应,本次连接就建立成功了。这无疑是浪费了服务端的连接资源
因此"三次握手"主要是为了防止失效的连接请求报文突然又传送到了服务端而造成错误;
TCP建立连接时需要"三次握手",断开连接时则需要"四次挥手";
原理图如下:
【第一次挥手】
客户端向服务端发送连接释放报文
。
连接释放报文
Tips:TCP规定,释放连接报文(FIN标记为1的报文)即使不携带数据也要消耗一个序号;
【第二次挥手】
服务端接收到来自客户端的连接释放报文
,由于服务端有可能正在该向客户端发送其他数据(还有数据未发送完),因此服务端不能立即发送释放连接报文,而是先向客户端发送一个确认报文表明连接释放报文
已经被成功接收;
连接释放报文
进行确认连接释放报文
中序号u的确认【第三次挥手】
服务端确认自身没有数据要发送客户端或者已经将数据全部发送完毕之后,开始发送连接释放报文给客户端,代表确认连接断开;
连接释放报文
,服务端与客户端断开TCP连接【第四次挥手】
客户端接收到来自服务端的连接释放报文
开始回复服务端的响应,服务端接收到响应后服务端的TCP连接释放;但客户端进入2MSL时间等待窗口,时间窗口到达后,客户端关闭TCP连接;
连接释放报文
的确认MSL(Maximum Segment Lifetime):报文最大生存时间,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。RFC793建议为2分钟,对于当前的网络环境,TCP允许不同的实现使用更小的MSL值;
连接释放报文
报文后不直接发送连接释放报文来关闭TCP连接,从而变成三次握手?服务端刚收到来自客户端的连接释放报文
后,有可能还再向此客户端发送数据,必须等到服务端发送完毕后再发送连接释放报文
给客户端。因此这一步的"握手"并不能省略。
连接释放报文
后不能直接关闭TCP连接,从而变成三次握手?如果少了最后一步的客户端确认动作,那么服务端无法得知客户端是否接收到服务端的连接释放报文
。并且在客户端发送完最后一次确认报文给服务对后客户端的TCP连接进入2MSL时间等待窗口,这是因为有可能客户端发送的确认报文超时了,此时服务端必定会要求客户端重传,因此客户端不能在发送确认报文完毕后就立即释放TCP连接,而是要进入一个时间等待窗口。
使用TCP协议传输数据时,必须要建立可靠连接(三次握手),当连接关闭时还需要四次挥手,对性能损耗较大,如果频繁的创建和关闭TCP连接性能势必会有很大影响。但是由于TCP的可靠传输,对一些数据完整性要求较高的场合比较适用,如文件上传下载等;
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。