传输层
负责端与端之间的数据传输。也就是说进程与进程之间的数据传输,进程用端口来表示,所以也可以叫做端口和端口之间的传输。
端口号
端口号为0-65535,一般0-1023为知名端口,不推荐使用,在一台主机上表示一个进程。
操作系统拿到网卡接收的数据之后,通过数据中的端口号知道数据放到哪一个socket缓冲区中
五元组
一条数据中包含的五个信息。源IP+源端口+目的IP+目的端口+协议
主机上网络状态的查看:netstat -anptu
传输层的传输协议
UDP协议
UDP协议的定义:无连接,不可靠,面向数据报
面向数据报:数据整条收发;灵活性低;但是不会造成粘包问题。每条数据有长度标识,数据有明显的间隔,带有报头的整条发,整条收,传输不灵活,但不存在粘包问题。
UDP不提供可靠性: 它把应用程序传给IP层(网络层)的数据发送出去,但是并不保证它们能到达目的地。UDP数据报封装成一份IP数据报的格式如图所示:
IP首部20字节,UDP首部8字节
UDP协议包含字段
UDP的协议字段包括源端口,目的端口,UDP长度,UDP校验和(总共8字节,统称为UDP首部)
源端口/目的端口
负责传输,为了确定数据应该哪个进程处理
校验和
通过二进制的反码求和,它也等价于二进制求和在取反
计算UDP校验和方法计算16位的二进制和,包括UDP首部数据。将校验和首先置为0,将每个16位的按位相加,第17,18位如果出现进位的话,将结果重新与结果的第1,2位相加,再将所得的结果取反码,最后得到的结果即为UDP校验和,存在校验和字段中。
数据报长度
UDP提供整条数据向应用层交付,实际上收到的数据都是经过检验过的,比如发送”ABCD“,不会出现“ABED”,只可能发生乱序或者丢包。因此如果发送成功但是是乱序的情况,那么用户需要在应用层进行包序管理。
UDP包的大小可以达到64K,但实际上以太网数据帧的长度必须在46~1500字节,这是由以太网的物理特性决定的。这个1500被称为链路层的MTU(最大传输单元)
如果直接发一个超过MTU的包,就会在协议层分片,这样的问题是如果一个分片在传输中出错了即校验不正确(这是较容易发生的),整个传输的UDP包可能就丢失了。
又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为64-8K。
UDP在传输层并不会进行分片,在IP层才会进行分片操作。
UDP的缓冲区
UDP没有真正意义上的缓冲区。调用sendto会直接交给内核,由内核数据传给网络层协议进行后续传输动作。
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送的UDP报的顺序一样。如果缓冲区满了,则再到达的UDP数据则会被丢弃。
TCP协议
TCP传输是面向连接,可靠传输,面向字节流
源端口/目的端口
一个IP地址和端口的组合称为“套接字”和端点,在IP协议中的源IP地址和目的地址和TCP协议中的源端口和目的端口,组成了“一对”套接字(发送端的套接字和接收端的套接字)
序列号
每一个TCP报文段中的第一个字节都会被赋予一个序列号。序列号是个32位数,到达2^32-1后会再回到0
确认序列号
也称ACK或ACK字段。确认号包含的值为”确认号的发送方“希望对方接收的下一个序列号。即序列号+数据长度。
4位TCP报头长度
表示TCP头部有多少个32位bit(有多少个4字节),由于"选项字段”大小是可变的,所以“头部长度”是必须的,TCP头部长度最大为60字节,如果没有选项字段,那么TCP头部长度为20字节。
6位标志位
URG: 紧急指针是否有效
ACK: 确认号是否有效
PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
窗口大小
在TCP协议中,一个分组从发送端发送到接收端中,接收端应该返回一个ACK号。
每一个分组都是从“序列号”开始的,我们定一个术语“窗口”,来表示:已发送的分组们,但这些分组还未返回确认号(ACK号)。窗口中的分组数量称之为:“窗口大小”,不会大于缓冲区的大小
下图为发送方的窗口以及其他分组队列:
如果发送方下一步接收到了序列号为4的分组“ACK”,则“窗口向右滑动一个分组”,意味着分组4可以释放了,分组7可以发送了。这种行为称之为:“窗口滑动协议”(下面详细叙述)
TCP校验和
该校验算法与IP、ICMP、UDP校验算法一致,其覆盖了TCP头部和数据中的一些字段。
紧急指针
只有在有URG字段时才有效。该指针是一个加到“序列号字段”上的正偏移,以产生“紧急数据”的最后一个字节的序列号。
面向连接
这就不得不在提到TCP的三次握手和四次挥手了。以客户端先发送请求为例。
三次握手
首先客户端先发送一个SYN包,请求建立连接。此时客户端处于SYN_SEND状态。这时服务端接收到了请求,会先发送一个SYN+ACK组合包确认一下是否建立连接。此时服务端处于SYN_RECV状态。当客户端接收到了组合包时,明白了服务端同意建立请求,这时客户端再次发送一个ACK包,’'表达"想要建立连接的决心,进行回复确认。当服务端再次收到这个ACK包之后,双方都处于ESTABLISH状态,此时双方可以互相发送数据信息了。
四次挥手
发送了一段数据之后,客户端想要断开连接。客户端向服务端发送一个FIN包,请求断开连接,此时客户端处于FIN_WAIT_1状态,等待ACK回复。服务端接收到了之后,向客户端发送一个ACK包,同意断开连接。此时服务端处于CLOSE_WAIT状态,客户端处于FIN_WAIT_2状态。这时服务端会在发送一个FIN包确认一下,是否断开连接,最后确认一次,此时服务端处于LAST_ACK状态。客户端收到该FIN包之后,会立刻回复一个ACK确认包,此时客户端处于TIME_WAIT状态,但是客户端会等待2个MSL(最大报文段生成时间),因为可能最后一次ACK包如果丢失的话,服务端会在发送一个FIN包过来。当在这个等待的时间内,服务端没有在发送之后,彻底断开连接,服务端和客户端都进入CLOSED状态。等待回收资源。
可靠传输
确认应答机制或者超时重传机制是保证安全到达
协议字段中的序号/确认序号是进行包序管理
校验和为了验证数据的一致性
因为TCP为了保证可靠传输,因此牺牲了部分传输性能;为了保证TCP传输性能不会进一步下降(因为ack丢失而重传),因此又有了一些新的机制。
滑动窗口机制+拥塞控制+快速重传机制
滑动窗口:
窗口是接收方为了告诉发送方最多发送多少,而不是非要让发送方发送多少。
通信双方通过协议中的窗口字段,来协商能够一次发送的最多数据,然后连续发送多条数据;在socket当中使用两个指针维护窗口后沿(起始位置)和前沿(发送的结束位置)。
发送端:若窗口中后沿数据没有接收到ack确认,后沿就不能向前移动,数据就不能从缓冲区移除,接收到ack确认后窗口,前后沿向后移动。
接收端:当接收数据的时候,如果没有接收到第一条数据,则后沿不能移动,只有接收到数据之后,后沿才会向前移动。
滑动窗口机制规定:
ack确认丢失的情况:每条数据都要进行回复,并且应该按序逐条回复,如果没有收到第一条,但是都到了第二条,第二条就不能先回复,应该先回复第一条;带来的好处就是,因为第一条ack丢失后,如果发送端收到第二条的回复,也会认为第一条正常接收;第一条就不需要重传了。
数据丢失的情况:当数据连续发送n条,但是第一条数据丢失,接收端先接收到第二条,这时候接收端认为第一条数据有可能丢失,因此直接开始向发送端发送第一条数据的重传请求;连续发送三次(防止网络延迟又接收到数据报);当发送端连接收到三条重传请求,则会对这条数据进行重传。
延迟应答机制
接收方接收数据后不立刻进行确认回复,而是等待一段时间,因为这段延迟的时间内,有可能用户recv将缓冲区中的数据取走,窗口就尽可能地保证最大窗口,保证传输地吞吐量。尽可能地保证滑动窗口地性能。
捎带应答机制
接收方对每一条数据地确认回复都需要发送一个TCP数据报;但是空报头地传输会降低性能
因此会考虑在即将要发送地数据报中包含有确认信息(可以少发一个确认的空报头)
面向字节流:传输字节流
发送方:每次调用send都会将数据放到缓冲区中,然后内核选择合适时机发送数据。
接收方:网卡接收到数据,都会将数据放到接收缓冲区中,用户recv就是从接收缓冲区中取数据
粘包问题主要发生位置
发送缓冲区中的数据堆积 or 接收缓冲区中的数据堆积
粘包本质原因:数据之间没有明显边界,tcp只管传输数据的字节流导致发送端/接收端因为数据的堆积在实际发送或recv时一次获取到半条或多条数据,这就是TCP的粘包问题
如何解决TCP粘包
TCP在传输层没有数据边界,但是用户可以在应用层进行边界处理。
**常见方法:**特殊字符间隔(比如HTTP协议);定长数据(UDP头中包含长度)
对于定长的包,保证每次都按固定大小读取即可;
对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;
对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序员自己来定的只要保证分隔符和正文不冲突即可);
TCP小结
为了保证TCP的可靠性,同时又尽可能地提高性能。
可靠性:校验和;序列号;确认应答;超时重发;连接管理;
提高性能:拥塞控制;流量控制;滑动窗口;超时重传;快速重传;延迟应答;捎带应带
TCP和UDP的比较
TCP和UDP之间并不能绝对的说谁比较好,而是通过场景来判断
TCP用于可靠传输,应用于文件传输,重要状态更新场景
UDP用于高速传输和实时性要求比较高的通信领域,比如视频传输。UDP还可以用于广播