TCP和UDP是OSI模型中传输层中的两个协议
TCP协议的特点:面向连接的 可靠的 字节流服务
UDP协议的特点:无连接的 不可靠的 数据报服务
为什么这样说呢,下面以我们来分析以上三点
一、服务类型
1、字节流服务
当发送端应用程序执行多次写操作,TCP模块先将这些数据放入TCP发送缓冲区中,当TCP模块真正开始发送数据时,发送缓冲区中等待发送的数据将被分装成一个或多个TCP报文段发出,当接收端接收到一个或多个TCP报文段后,TCP模块将发送端发送的数据按照TCP报文段的序号依次放入TCP接收缓冲区,并通知应用程序读取数据,接收端应用程序可以一次将TCP接收缓冲区中的数据读取完,也可以分多次读取,这取决于应用程序读取缓冲区的大小,发送数据或接收数据时,数据有可能被分开或者合并,如果发送端发一次数据,接收端一次未接收完,数据不会丢失。
字节流服务:发送端发送数据的次数与接收端接收数据的次数没有关系。
2、数据报服务
发送端应用程序执行一次写操作,UDP模块就将其分装成一个DUP报文段并发送出去,接收端应用程序必须及时对每一个UDP报文段执行读操作(通过recvfrom系统调用函数),否则会出现丢包,如果接收端应用程序recvfrom一次未将数据读取完成,则UDP报文段中剩下的数据丢失。
数据报服务:发送端发送数据的次数与接收端接收数据的次数相等。
二、可靠性
1、TCP可靠传输
16位源端口号:告诉主机报文段来自那里。
16位目的端口号:告诉主机传给那个上层协议或应用程序。
32位序号:第一个报文段系统会生成一个随机值,后续报文段的序号是报文段携带的数据的第一个字节在整个字节流中的偏移量加上生成的随机值。
比如某个数据有100个字节
报文段个数 报文段字节 序号值
第一个报文段 30个字节 2000
第二个报文段 20个字节 2030
第三个报文段 50个字节 2050
32为确认号:由接收端填充,其值是接收到的报文段的序号值加1,对接收到的报文段确认。
4位头部长度:标识该TCP头部有多少个32bit字(4字节),4位最大表示15,所以TCP头部最长60个字节。
6位标志位
紧急URG:表示紧急指针是否有效,URG=1时表示紧急指针字段有效。
确认ACK:表示确认号是否有效,ACK=1时表示确认号字段有效,ACK=0时表示确认号字段无效,TCP规定,在连接建立后所有传送的报文段都必须把ACK置为1。
推送PSH:提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就一直停留在TCP接收缓冲区中)。
复位RST:表示要求对方重新建立连接,RST=1时表示TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接,RST=1还用来拒绝一个非法的报文段或拒绝打开一个连接。
同步SYN:表示请求建立一个连接,当SYN=1而ACK=0时表示这是一个连接请求报文段,对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1,因此SYN=1表示这是一个连接请求或连接接受报文。
终止FIN:表示通知对方本端要关闭连接了,当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。
16位窗口大小:指的是接收通告窗口,它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度,这是TCP流量控制的一个手段。
16位校验和:由发送端填充,接收端通过CRC算法对TCP报文段的头部和数据进行校验,检验TCP报文段在传输过程中是否损坏,这是TCP可靠传输的一个重要保障。
16位紧急指针:是一个正的偏移量,指出紧急数据的末尾在报文段中的位置,当所有紧急数据都处理完时,TCP就回告诉应用程序回复到正常操作,当窗口为0时也可发送紧急数据。
TCP报头最小20个字节,最大60个字节
TCP的可靠传输体现在以下三个方面:
1> 所有数据都能到达对端 32位确认号
2> 数据不乱序 32位序号
3>数据不出错 16位校验和
2、UDP不可靠传输
16位源端口号:告诉主机报文段来自那里。
16位目的端口号:告诉主机传给那个上层协议或应用程序。
16位UDP长度:表示UDP报文段的总长度。
16位UDP检验和:检测UDP报文段在传输中是否有错,有错就丢弃。
和TCP头部对比,可以看出UDP头部并没有做一些可靠控制机制,只是尽最大努力交付,因此UDP是不可靠传输。
三、是否建立连接
1、TCP的三次握手和四次挥手
1> 客户端向服务器发出连接请求报文段,在请求报文段中将同部位SYN置为1;
2> 服务器收到连接请求报文段后,如果同意建立连接,则向客户端发送确认,在确认报文段中将确认位SYN和同步位SYN都置为1;
3> 客户端收到服务器的确认后,还要向服务器给出确认,在确认报文段中将确认为ACK置为1。
这时TCP的三次握手完成,连接建立,接下来,客户端可以和服务器相互发送数据。
1> 主动断开方向被动断开方发送断开连接报文段,并停止发送数据,在断开连接报文段中将中止为FIN置为1;
2> 被动断开方收到断开连接报文段后立即发出确认,在确认报文段中将确认为ACK置为1,这时TCP连接处于半关闭状态,主动断开方到被动断开方的连接就释放了,但被动断开方到主动断开方仍处于连接状态,因此被动断开方可以向主动断开方发送数据;
3>当被动断开方的数据发送完成后,被动断开方向主动断开方发送断开连接报文段,在断开连接报文段中将中止为FIN置为1;
4>主动断开方收到断开连接报文段后发出确认,在确认报文段中将确认为ACK置为1;
这时连接并没有断开,当 主动断开方等待2MSL后,TCP四次挥手完成,连接释放。
为什么主动断开方在TIME-WAIT状态必须等待2MSL才能断开连接呢?有两个原因
1> 保证主动断开方发送的最后一个ACK报文段能够到达被动断开方;
2> 保证被动断开方在CLOSE-WAIT状态发送的数据能被识别并丢弃。
2、UDP无连接
UDP在发送数据之前不需要建立连接,因此减少了首部开销和发送数据之前的时延。