一、传输层提供的服务
如果说应用层的http协议决定怎么使用接收的数据,和接下来要发送什么数据。
那么传输层的作用就是保证这些数据能准确的发送/接收到应用层。
传输层的报头中会保存目的端口号,这标识着发送方所请求的唯一的应用程序。
1.端口号范围划分
- 0-1023 : 知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的。
- 1024-65535 : 操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的。
2.认识知名端口号(Well-Know Port Number)
有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:
名称 | 端口号 |
---|---|
ssh服务器 | 22 |
ftp服务器 | 21 |
telnet服务器 | 23 |
http服务器 | 80 |
https服务器 | 443 |
一个进程可以bind多个端口号,但是一个端口号只能被一个进程bind。
3.Linux下相关命令
netstat
- netstat是一个用来查看网络状态的重要工具。
pidof [进程名]
- 通过进程名,查看进程ID。
- 进程ID不是端口号,因为一个进程只能对应一个进程ID,而可以有多种端口号访问到这个进程。
二、UDP协议
1.UDP的报头格式
- 16位的UDP长度表示整个数据报(UDP首部+UDP数据)的最大长度。
- 如果校验和出错,就直接丢弃。
- 目的端口号就是表明要交给应用层的哪一个应用程序
2.UDP的特点
- 无连接:在使用UDP协议传输的时候,只需要知道对方的IP地址和端口号,就可以直接进行传输,不需要进行链接。
- 不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。
- 面向数据报:应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
3.UDP的缓冲区
- UDP没有真正意义上的发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。
- UDP具有缓冲区,但是这个缓冲区不能保证收到的UDP报的顺序和发送的UDP的顺序一致,如果缓冲区满了,再到达的UDP数据报就会被丢弃。
- UDP的socket既能读,也能写,这个概念叫做全双工。
4.UDP使用注意事项
- UDP协议首部有一个16位的总长度,也就是一个UDP数据报能够传送的最大长度是64K(包括数据报头)
- 然而在如今的网络环境中,64K是一个非常小的量,如果我们想要传输的数据超过64K,就需要在应用层手动的分包多次发送,然后在接收端应用层进行拼装。
5.基于UDP的应用层协议
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
- 包括自己自定义的应用层协议
三、TCP协议
TCP全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制。
1.TCP的报头格式
- 源/目的端口号,表明这个数据报是从哪个进程发送过来的,要由哪个进程来接收
- 序列号/确认序号:TCP协议是一种全双工(可以同时发消息)的协议,所以TCP报头中的序号和确认序号是保证通信双方的信息都具有可靠性
- 4位首部长度:表示该TCP报头含有多少个32位(多少个4字节),说明除了默认的20字节的数据报头长度之外,选项部分的长度最多占40字节。
- 6位标志位:
- URG:紧急指针是否有效。
- ACK:确认号是否有效。
- PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走。
- RST:对方要求重新建立链接,我们把携带RST标识的称为复位报文段。
- SYN:请求建立链接,我们把携带SYN标识的称为同步报文段。
- FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段。
- 16位窗口大小:标识发送端接收缓冲区剩余空间的大小。
- 16位校验和:发送端填充,CRC校验,接收端校验不通过,则认为数据有问题。
- 16位紧急指针:标识哪部分数据是紧急数据。
2.TCP可靠性的体现
校验和
- 如果校验出错会让发送端重发数据,而UDP校验出错直接丢弃数据。
序列号
- 保证所有数据报的按序到达。
确认应答机制
- 如果发送端第一次发送一个序列号为1的数据报,那么接收端接收到数据之后,要回信发送端数据报时,将确认序号置为2:标识接收端希望发送端下一次发送数据序号从2开始。并且接收端自己也有一个序号。当发送端收到回信时,按相同的步骤再次发送给接收端。
超时重传机制
- 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达B。如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发。
- 如果是主机B回信的确认数据报丢失了,主机A也还是会给B重新发送。随便主机B会收到重复的数据报,但是可以利用序号做到去重。
链接管理机制
- 在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接。
- 三次握手图解:
- 为什么不是两次握手?
- 答:因为两次握手,服务端的确认数据报如果丢失了,服务端认为链接建立成功,就会给客户端IP开辟一段空间,浪费资源。
- SYN攻击
在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.
Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击. - 四次挥手图解:
- 因为TCP链接是全双工的。所以断开链接的时候双方必须都发出断开链接的请求。没有先后的规定。
流量控制
- 接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区没有剩余空间。这个时候发送端要是继续发送,就会造成丢包,继而引起丢包重传等待一系列连锁反应。
- 因此TCP支持根据接收端的处理能力,来决定发送端的发送能力,这个机制就叫做流量控制。
- 接收端在发送ACK确认发送端的消息的时候,会用自己报头中的16位窗口大小表示接收缓冲区的大小,如果缓冲区有变化,那么这个数值也会相应的改变。
- 发送端发现16位窗口大小变小之后会减慢自己的发送速度,如果发现接收端16位窗口大小为0的时候,发送端停止发送数据,但是会定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
- 16位数字的最大值表示65535,但是窗口大小的最大值不是65535字节。在TCP选项中还包含一个窗口扩大的因子M,实际窗口大小的值,是16位窗口大小值左移M位。
拥塞控制
- 虽然TCP有滑动窗口,能够高效可靠的发送大量数据,但是如果在网络刚连接的时候,就贸然发送大量数据是不可以的。因为不清楚网络目前的状况,如果网络中的流通数据很多,这样势必会雪上加霜。
- TCP引入慢启动机制,在最初的时候先发送少量的数据“探探路”,如果收到了准确的ACK确认数据报,下次就多发送一些数据。
- 此处引入一个概念叫做拥塞窗口,发送开始的时候,定义拥塞窗口为1,每收到一个ACK应答,拥塞窗口加1,每次发送数据报的时候,发送端将拥塞窗口和接收端反馈的16位窗口大小做比较,取最小值作为实际可以发送的数据的最大值。
- 慢启动的意思就是,用指数增长的方式定义拥塞窗口。但是为了防止后面拥塞窗口增长的太快,定义了一个拥塞窗口的阈值,如果超过这个阈值,就不再按照指数增长,而是线性方式增长。
- 拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.
- 当超时重传的时候,拥塞窗口会重置,它的阈值变为超时时候窗口大小的二分之一,然后窗口重新从1kb 开始。
3.TCP如何提高性能
滑动窗口
- 根据TCP的确认应答机制,我们知道TCP每发送一个数据报都会等待一个确认数据报。收到之后才会发送下一条数据。
- 这样的发送效率太低,大多时间都用来等待确认数据报。那么我们可以一次发送多个数据报,然后一起等待确认数据报。
- 滑动窗口的大小就是,无需等待确认应答而可以继续发送数据的最大值。
- 滑动窗口工作原理:
- 如果收不到确认,那么滑动窗口大小就会减少。
- 丢包情况一:如果部分接收端的确认应答丢失了,不用怕。因为发送端可以通过之后过来的确认应答序号得知之前的数据报接收端已经正确收到了。
- 丢包情况二:如果发送端发送的数据报丢了,例如:先发送1-1000,那么接收端的确认应答应该是1001,发送端接着发送1001-2000,但是数据报丢了,接收端没有收到这个数据报,之后接收端收到任何数据报,都会继续发送1001的确认应答(但是这个时候的任何数据报接收端都已经正确接收)。当发送端收到三次重复的1001。就标识着接收端希望他再次发送1001-2000的数据报。当发送端正确发送1001-2000时,接收端会回复一个7001的确认应答。因为在这个期间其他的数据报都正确接受了,组装起来之后,发送最后一个数据报的确认应答。
- 上面这个情况二,也叫做快重传机制也是一种提高性能的做法。
延迟应答
- 接收端如果刚接收到发送端的数据报就发送自己的确认应答,那么它的接收窗口大小势必较小。
- 因为数据处理的速度很快,接收端如果能稍微等待一下,等应用层快速提取数据,那么接收端的接收窗口大小就比直接确认应答的大小要大。
- 一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高,我们的目标是在保证网络不拥塞的情况下尽量提高传输效率。
捎带应答
- 在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给服务器说了 “How are you”, 服务器也会给客户端回一个 “Fine, thank you”;
- 那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端
4.TCP的其他特性
面向字节流
- 这一点和UDP的面向数据报不一样
- 创建一个TCP的socket,同时在内核中创建一个发送缓冲区和一个接收缓冲区。因为TCP是全双工的链接。
- 调用write时,数据会先写入发送缓冲区中,如果发送的字节数太长,会被拆成多个TCP的数据报发送出去。
- 接收数据的时候,也是从网卡驱动程序到达内核的接收缓冲区,然后应用程序调用read从缓冲区中拿数据。
- 由于缓冲区的存在, TCP程序的读和写不需要一一匹配,。
粘包问题
- 首先要明确,粘包的“包”是应用层的数据包。
- 当接收端收到TCP的数据报时候,虽然有序号。但是站在应用层的角度,它看到的是一连串的字节数据,就不知道从哪个部分到哪个部分是一个完整的数据包。
- 对于定长的包,每次按固定大小读取就行了。
- 如果是变长的包,可以在数据包中定义一个包长度字段。也可以用分隔符分开每个数据包。
- UDP不存在粘包问题,因为它每次发送的都是一整个数据包,不存在发送“半个”的可能。