网络中传输层协议

传输层:

传输层主要是负责应用程序之间的数据传输,传输层主要的协议有TCP和UDP

(一)UDP:

UDP:无连接、不可靠、面向数据报的传输

UDP的协议格式:
在这里插入图片描述

  1. 16位的源端口/16位的目的端口:描述数据从哪个进程发送到哪个进程 – 负责实现应用程序间的数据传输
  2. 16位的数据报长度:包含UDP报文头部在内的整体报文长度,16位存储的最大数字为65535
  3. 16位的校验和:二进制反码求和算法,用于校验接收到的数据和发送的数据是否一致
    发送方在发送数据之前,校验和为0,从完整报文的第0个字节开始,每个字节进行取反相加,超过16位的部分取出来,再次与低16位进行相加,最后得到一个校验和填充到协议字段中
    接收方接收到数据之后,从完整报文的第0个字节开始,每个字节进行取反相加,最终的结果如果为0,则表示数据一致,否则则表示数据不一致

1.无连接:

无连接是指通信的时候不需要建立连接,只需要知道对方的地址信息,就可以发送数据

2.不可靠:

不可靠是指在通信中并不保证数据安全可靠以及有序的到达对方

3.面向数据报:

面向数据报是指在UDP传输时,对于上层协议传过来的数据既不合并也不拆分,直接添加上一个UDP头部就开始传输

面向数据报:无连接、不可靠、有最大传输长度限制的一种传输方式,一个完整的udp报文的总长度不能超过64k(由UDP头部中的数据长度决定)

  1. 影响1:若sendto传输的数据长度大于64k-8,则传输会报错,因此数据过长,需要程序员在应用层自己手动将大数据分割成一个个小的数据段(<64k-8)进行sendto发送
  2. 影响2:但是因为udp并不保证数据有序到达,这时候在上层,程序员进行数据分包之后,就要考虑在应用层实现各个数据段的包序管理
  3. 影响3:udp报文都是整条收发的;因为udp报文头部中定义了报文长度,因此sendto发送数据的时候,数据一到发送缓冲区就会直接封装udp报文头部,然后发送数据(udp的socket发送缓冲区形同虚设,因为并没有起到数据缓冲的作用),接收方接收到数据,放到接收缓冲区中,用户recvfrom接收的时候不会出现接收到半条数据(接收半条头部就没了,就不知道接收多少数据了)或者两条数据的情况,只能是一条完整的数据
  4. 影响4:udp使用recvfrom获取数据的时候,给的buffer要足够大,防止出现数据过长给的buffer不够而报错,接收失败的情况

(二)TCP:

TCP是有连接的可靠的面向字节流的传输
TCP的协议格式:

在这里插入图片描述

  1. 16位的源端口和目的端口:负责应用程序之间的数据传输
  2. 32位序号/32位确认序号:实现确认应答机制以及接收端的包序管理
  3. 4位头部长度:表示TCP头部有多少,TCP头部是不定长的,主要取决于选项数据的大小,TCP头部最小为20字节,最大60字节(选项数据中占0~40字节)
  4. 6位保留位:目前没有想好用来干什么,先预留出来用于以后扩展
  5. 6位标志位:URG/ACK/PSH/RST/SYN/FIN
  6. 16位窗口大小:表示本端可以接收的数据大小,用于实现滑动窗口机制,进行流量控制
  7. 16位校验和:二进制反码求和算法,校验数据接收与发送的一致性
  8. 16位紧急指针:标识哪些数据是紧急数据(带外数据)
  9. 0-40字节的选项数据:通常用于协商一些信息如MSS的长度

1.面向连接:

面向连接指的是在双方进行通信之前需要先建立连接,建立连接后系统就会创建一些数据结构以及资源来维护这些连接,在通信结束后,需要断开连接
监听套接字只有一个,处于LISTEN状态,用于监听新的连接的到来
处于ESTABLISHED状态的套接字都是链接套接字

  1. 三次握手建立连接:
    在这里插入图片描述

  2. 四次挥手断开连接:
    在这里插入图片描述

2.可靠:

TCP的可靠主要是使得数据能够有序并且安全不丢包的到达对端
有序是通过协议中的序号来管理包序
安全则是通过确认应答、超时重传、流量控制、拥塞控制、以及校验字段来实现

  1. 确认应答机制:对于发送的每一条数据都要求接收方进行确认回复(通过TCP头部中的确认号以及ACK标志来实现)

  2. 超时重传机制:在指定时间内没有收到确认回复,则认为数据丢失,对之前的数据进行重传

  3. 协议字段中的序号和确认序号:进行包序管理,并且实现确认应答机制

  4. 确认序号:告诉发送方这个确认序号之前的数据都已经收到,下次发送数据从该序号开始发送----如果第一条数据丢失,就算收到第二条也不会回复,因为每一条回复表示的含义都是前面的数据全部收到了,这种方式可以避免因为ack确认回复的丢失而导致的重传—效率就变高了,如果没有这个确认号,连续发送几个数据后,已经收到了数据,但是ACK回复丢失了,对方也要给你重新发送数据

  5. 协议字段中的校验和:检验数据是否一致,不一致则要求对方重传
    哪一条数据不一致则回复这条数据的起始序号,比如:1~1024数据不一致,就回复确认序号1,要求对方重传1起始的数据

  6. 滑动窗口机制:通过滑动窗口就可以实现数据的连续发送以及进行流量控制,避免发送数据过多而导致丢包。

    通过协议字段中的接收窗口大小实现—通过窗口大小告诉对方最多发送多少数据,避免因为发送数据过多,接收缓冲区溢出,导致丢包
    在三次握手的时候,通信双方会通过选项数据协商一个信息—MSS 最大数据段大小(不包含头部);TCP发送数据的时候,会从发送缓冲区中取出不大于MSS大小的数据封装TCP头部进行发送。
    窗口大小通常不大于接收方的接收缓冲区的剩余空间大小

  7. 拥塞控制机制:滑动窗口实现一次连续发送多条数据,但是网络不好,一开始在网络状态不明的情况下,有可能因为网络情况,导致发的越多丢时的越多-----因此在发送数据时,进行网络探测,查看网络是否能够支持数据的连续快速传输
    实现的原理:慢启动、快增长,通过拥塞窗口实现,拥塞窗口刚开始进入网络是设置为1MSS大小
    在这里插入图片描述

  8. 快速重传机制:提高传输性能----不用等待超时,然后重传。
    发送方连续发送多条数据时,若接收方首先接收到了第二条数据,则有理由认为第一条数据丢失了,因此开始连续发送三条第一条数据的确认请求,发送方接收到连续三次重传请求,则会对这条数据进行重传。三次的原因:有可能前面的数据只是延迟了,而并非丢失了,三条重传请求之间就可以有一个缓冲时间,这个时间内若收到了第一条数据,三次重传请求没有发送完,则发送端就可以不用重传了

    重传这里存在三种协议:停止等待协议/选择重传协议/回退n步协议—属于滑动窗口中的协议

    1. 停止等待协议:滑动窗口没有什么意义,收到第一条回复才会发送第二条数据—适用于网 络状况特别差的场景
    2. 选择重传协议:哪条丢了就重传哪条
    3. 回退n步协议:从丢失的那条数据开始把后面的数据都重新发一次
      在这里插入图片描述
  9. 提高效率的机制:
    1. 延迟应答机制:因为接收方若接收到数据之后立即回复,则窗口大小会变小,传输吞吐率就会降低,因此接收方使用延迟应答机制,延迟一段时间再确认回复,因为在延迟的这段时间内,数据就可能被用户取出,保证传输吞吐率
    2. 捎带应答机制:因为每一条确认回复,都是一个确认回复序号,但是为了确认回复都必须组织一个tcp数据包发送给对端,就会造成大量的空包发送,若接收方即将发送一条数据给对端,则可以在这条即将发送的数据包头中对上一条数据进行确认回复,节省了一个空报头的传输

总结:

  1. 可靠传输的实现:面向连接/确认应答机制/超时重传机制/序号/确认序号/校验和
  2. 避免丢包:滑动窗口机制/拥塞避免机制
  3. 提高性能:快速重传机制/延迟应答机制/捎带应答机制

3.字节流:

字节流传输指的是数据可以在缓冲区中进行堆积,用户取数据的时候就从缓冲区里面想取多少可以取多少,以字节为单位,比较灵活
发送缓冲区中有很多数据,tcp就会根据mss取出合适大小的数据进行传输,
接收缓冲区中有很多数据,tcp也可以灵活的以用户需要的大小向上交付

数据在缓冲区堆积有一个TCP粘包的问题:将多条数据当作一条数据来处理

粘包的本质原因:tcp在传输层对数据边界不敏感(不管上层数据是什么样的,每次都根据mss取出合适大小进行发送/不管接收缓冲区中是什么数据,只管从缓冲区中取出用户需要的大小的数据),因此造成了粘包的问题
粘包的解决方案程序员在应用层进行数据的边界管理

  1. 特殊字符进行间隔 ---- 每条数据结尾有个特殊字符作为结尾,但是我们传送的数据中也有可能有这个字符
  2. 数据定长 ---- 每次只发送/接收指定长度的数据,数据短了造成大量的资源浪费
  3. 在应用头部中定义数据长度字段 ---- 先按照指定长度将头部获取,根据头部中的长度,取出指定长度的数据(类似UDP) ----最典型的就是http中,用\r\n间隔,头部中Content-Length定义正文的长度

(三)常见面试题:

  1. 握手为什么是三次?两次不安全/四次没必要
    Tcp是双向通信,必须确保双方都具有数据收发的能力;假设客户端发送请求连接后直接退出了,因此都要给对方发送SYN请求

  2. 握手失败服务端是怎么处理的?
    主要是第二次的握手过程失败—若服务端回复ACK+FIN后迟迟得不到ACK回复,则服务端会发送RST重置连接报文,然后销毁socket
    SYN泛洪攻击:恶意主机,不断的发送SYN请求给服务器,但是不进行最后一个ACK回复—消耗服务器的连接资源

  3. 挥手为什么是四次?
    发送FIN包只能表示不再给对方发送数据,不代表不再接收数据,因此被动关闭方对FIN确认回复后,依然有可能要发送数据,主动关闭方可能还会接收数据,正因如此,被动关闭方不能把ACK与FIN合成一个数据报进行发送(但是有可能刚好被动关闭方也要关闭连接,所以四次挥手也可能是三次挥手)

  4. 主动关闭方的TIME_WAIT状态有什么用?–用来保护主动关闭方,避免立即使用相同的地址信息对后续通信造成影响
    假如没有TIME_WAIT状态会出现什么情况:主动关闭方直接释放socket,意味着端口和地址可以立即重新使用,若最后一次主动关闭方ACK丢失,等待超时后被动关闭方就会重传一个FIN包,假如主动关闭方主机释放之后立即使用了刚才套接字的端口和地址信息重新启动了程序,1.新的程序使用原先的地址信息与对方通信,就收到了这个重传的FIN包2.新的程序使用原先的地址信息连接相同的服务器,而这个服务器正在等待最后一次ACK,而这次连接给建立时给服务器发送的是一个SYN请求连接包 ----------- 如果主动关闭方没有TIME_WAIT直接释放资源,新程序就有可能立即使用了上一次相同的地址信息,上一次的通信就可能会对新建的通信造成影响,因此主动关闭方必须等待一段时间—(2MSL—两个报文的最大生存周期),能够处理被动关闭方可能重传的FIN包,并且等待本次通信的所有数据都消失在网络中,避免对后续连接造成影响,

  5. 一个主机上出现了大量的CLOSE_WAIT是什么原因?
    证明你的代码有问题,连接断开后没有close关闭套接字释放资源

  6. 一个主机上出现了大量的TIME_WAIT是什么原因?
    TIME_WAIT是主动关闭方才会有的状态,常出现于爬虫服务器,大量的主动关闭了连接
    地址重用 / 缩短TIME_WAIT等待时间

  7. TCP连接管理中的保活机制:tcp协议是面向连接的,若通信双方长时间没有数据往来,就需要确定对方还是否在线,连接是否正常,若通信双方长时间(7500s)没有数据往来,则服务端会每隔一段时间(75s)向客户端发送一个保活探测数据包,要求对方响应,若多次(9次)无响应,则认为连接断开(可以配置—通过设置套接字选项—setsockopt)
    连接断开对上层程序编写的影响:被动关闭端recv返回0,关闭端send触发异常

  8. recv的原理:操作系统把网卡接收的数据放到对应socket的接收缓冲区中,然后通过就绪描述符找到socket,然后从接收缓冲区中取出想要的大小的数据
    send就是将想要发送的数据放到发送缓冲区中,tcp会从缓冲区中取出合适大小的数据进行数据封装然后发送

  9. UDP粘包怎么解决:UDP不会产生粘包,因为UDP是整条收发的,而且UDP的头部中还有数据的长度

  10. Tcp协议和udp协议有什么区别:
    1.TCP是面向连接的,UDP是不面向连接的……
    2.TCP是可靠的,UDP是不可靠的……
    3.TCP是面向字节流的UDP是面向数据报的……
    Udp速度快,但是不可靠,tcp是可靠的传输但是速度相对慢,而且用到的资源也比较多

  11. UDP怎么实现可靠传输?
    先回答TCP实现可靠传输的机制,然后说把TCP实现可靠的机制拿到UDP的应用层中就可以实现UDP的可靠传输

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值