Linux知识点 -- 网络基础 -- 传输层

Linux知识点 – 网络基础 – 传输层

文章目录

  • Linux知识点 -- 网络基础 -- 传输层
  • 一、传输层协议
    • 1.端口号
    • 2.网络相关bash命令
  • 二、UDP协议
    • 1.UDP报文的解包与交付
    • 2.理解UDP报文
    • 3.UDP协议的特点
    • 4.UDP应用层IO类接口
    • 5.UDP的缓冲区
    • 6.UDP使用注意事项
    • 7.基于UDP的应用层协议
  • 三、TCP协议
    • 1.TCP报文的解包与交付
    • 2.理解TCP协议的报文
    • 3.理解TCP协议的可靠性
    • 4.序号和确认序号
    • 5.TCP的缓冲区
    • 6.16位窗口大小
    • 7.6个标记位
    • 8.TCP的建立连接(三次握手)
    • 9.TCP的断开连接(四次挥手)
    • 10.确认应答机制 -- 可靠性机制
    • 11.超时重传机制 -- 可靠性机制
    • 12.流量控制 -- 可靠性机制
    • 13.滑动窗口 -- 提高效率机制
    • 14.拥塞控制 -- 可靠性机制
    • 15.延迟应答 -- 提高效率机制
    • 16.捎带应答 -- 提高效率机制
    • 17.TCP机制总结
    • 18.面向字节流
    • 19.粘包问题
    • 20.TCP异常
    • 21.TCP和UDP对比
    • 22.用UDP实现可靠传输


一、传输层协议

1.端口号

端口号标识了一个主机上进行通信的不同的进程;
在这里插入图片描述
在TCP/IP协议中,用源IP、目的IP、源端口号、目的端口号、协议号这样一个五元组来标识一个通信;
在这里插入图片描述

  • 端口号范围划分:
    0 - 1023:知名端口号,HTTP, FTP, SSH等这些广为使用的应用层协议,他们的端口号都是固定的;
    在这里插入图片描述
    1024 - 65535:操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的;

  • 一个进程可以bind多个端口号;

  • 一个端口号不可以被多个进程bind;

2.网络相关bash命令

  • netstat:查看网络状态
    常用选项:
    在这里插入图片描述
    最常用命令:
    netstat -ntlp
    netstat -tlp

    在这里插入图片描述
    netstat -nup
    netstat -nupa

    在这里插入图片描述

  • pidof:返回当前进程的pid
    在这里插入图片描述
    在这里插入图片描述
    xargs将标准输入以命令行参数的方式交给后面的命令,这样kill -9命令拿到的参数就是以参数形式传递的,等价于kill -9 pid;
    在这里插入图片描述
    这样就是以标准输入的方式交给后面的指令,对于kill是不行的;

二、UDP协议

1.UDP报文的解包与交付

  • UDP报文格式:
    在这里插入图片描述

  • UDP协议报文的解包:
    UDP的报文是固定长度的,分离时直接将报头提取出来,留下有效载荷;

  • UDP协议报文的交付:
    报文中提供了目的端口号,根据此16位端口号向上交付,进程bind了端口号;

  • 应用层编写代码时,端口号是uin16_t类型的,这是因为UDP协议中的端口号是16位的;

  • UDP如何提取完成报文:
    UDP报头中有16位UDP长度,且报头是固定长度,因此根据长度就能提取完整报文;

2.理解UDP报文

在这里插入图片描述
UDP报文都是使用位段实现的,位段就是对象,是能够拷贝的;
封装报头:内核定义报头对象,将用户数据拷贝到内核缓冲区,将报头对象拷贝到用户数据前面;

在这里插入图片描述

3.UDP协议的特点

  1. 无连接知道对端的IP和端口号就直接进行传输,不需要建立连接;
  2. 不可靠没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息;
  3. 面向数据报不能够灵活的控制读写数据的次数和数量;
    应用层交给UDP多长的报文,UDP原样发送,不会拆分和合并;

4.UDP应用层IO类接口

  • sendto/recvfrom/write/read/recv/send …IO类接口其实不是在网络中进行数据的收发,而是从内核层缓冲区中拷贝数据,或者拷贝到内核层缓冲区;
  • 缓冲区都是传输层提供的;
  • 数据的发送细节都是由UDP协议控制的,什么时候发,一次发多少,出错怎么办,都是由操作系统处理的;

5.UDP的缓冲区

  • UDP没有真正意义上的发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
  • UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致;如果缓冲区满了,再到达的UDP数据就会被丢弃;
  • UDP的socket既能读也能写,这个概念叫做全双工

6.UDP使用注意事项

UDP协议首部中有一个16位的最大长度,也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部);
然而64K在当今的互联网环境下,是一一个非常小的数字,如果我们需要传输的数据超过64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装;

7.基于UDP的应用层协议

NFS:网络文件系统
TFTP:简单文件传输协议
DHCP:动态主机配置协议
BOOTP:启动协议(用于无盘设备启动)
DNS:域名解析协议

三、TCP协议

1.TCP报文的解包与交付

  • TCP报文结构:
    在这里插入图片描述
  • TCP协议交付:
    TCP通过目的端口号决定报文交付的进程;

TCP报头由固定长度的属性(20字节)和选项(最多40字节)构成,因此报头长度为]20,60]字节;
4位首部长度:表示TCP报头长度的属性,表示的大小为0-15,单位是4字节,最终能表示20-60字节的报头长度,因此4位首部长度的取值范围是5-15;

  • TCP协议解包:
    (1)提取20字节;
    (2)根据标准报头,提取4位首部长度 * 4 = 20 - done;
    (3)读取 [提取4位首部长度* 4- 20] 字节数据,选项;
    (4)读完了报头,剩下的都是有效载荷;

注意:TCP报头中没有有效载荷的大小;

2.理解TCP协议的报文

TCP报文也是一个位段结构,与UDP类似;

3.理解TCP协议的可靠性

在操作系统单机内部,我们不谈协议,但是已到了网络层面,就需要用到协议,这是因为距离变长了,数据的可靠性就下降了;

网络中不存在100%可靠的协议,任一方都无法保证自己作为数据发送方发送的所有数据都被对方接收;

但是,在局部上,我们可以做到100%可靠:
我们发出去的消息,只要有匹配的应答,就能够保证对方一定接收到了;

因此,TCP协议的确认应答机制:只要一个报文收到了对应的应答,就能保证发出的数据被对方接收到了;
在这里插入图片描述

4.序号和确认序号

实际TCP的通信过程中,不是一个报文发送了,接收到该信号的应答后再发送下一条报文,而是一次发送多条报文,这样接收方接收到的报文有可能是乱序的;
TCP报头中的序号和确认序号就是用来帮助接收端确认报文顺序的:

  1. 将请求和应答进行一一对应;
  2. 确认序号 – 表示的含义:确认序号之前的数据已经全部收到,下次发送从确认序号之后的序号发送;
  3. 允许部分确认丢失,或者不给应答;
  4. 为什么要有两个字段数字?
    任何通信的一方,工作方式都是全双工的,在发送确认的时候,也可能携带新的数据;
    在这里插入图片描述

5.TCP的缓冲区

TCP有发送缓冲区和接收缓冲区,并且是全双工通信
收发数据都是将数据拷贝到缓冲区,交给操作系统,细节流程都是由TCP协议控制;

在这里插入图片描述

6.16位窗口大小

TCP协议发送的数据都是先暂存在对方主机的传输层缓冲区上的,缓冲区是有大小限制的,因此发送数据的一方,不能发太快,也不能发太慢,也就是说发送的时候要进行流量控制

  • 那么依据什么进行流量控制呢?
    一台主机的接受能力,是由接收缓冲区中剩余空间的大小来决定的,16位窗口大小就是己方主机接收缓冲区剩余空间大小,里面填的是自己主机的剩余缓冲区大小,发送给对方主机,给发送方同步自己的接受能力,让其知道我们的接收缓冲区还剩多少空间;

7.6个标记位

  1. SYN该位置1,表明该报文是一个链接请求报文;
  2. FIN该位置1,表明该报文是一个断开链接请求报文;
  3. ACK确认应答标志位,凡是该报文具有应答特征,该标志位都会被设置为1;大部分网络报文ACK都是被设置为1的;
  4. RST该位置1,表明该报文是一个链接重置请求报文;
    连接未建立成功或出现异常,想让对方关闭连接,服务端向客户端回复报文,将RST标志位置位,客户端就会将连接关闭;
  5. PSH该位置1,催促对方尽快将数据进行向上交付;
    检测到对方窗口大小为0,督促对方交付数据;
  6. URG紧急标志位,表明该报文高优先级交付;
    与URG功能对应的还有16位紧急指针;
  • 16位紧急指针指向的是报文中紧急数据在有效载荷中的偏移量,当URG置位时有效,通常是用来进行机器管理;

8.TCP的建立连接(三次握手)

在这里插入图片描述
因为有大量的client将来可能链接server,所以server端一定会存在大量的连接;
OS要不要管理这些连接?先描述,再组织!
所谓的连接:本质其实就是内核的一种数据结构类型,建立连接成功的时候,就是再内存中创建对应的连接对象,再对多个连接对象进行某种数据结构的组织;
维护连接是有成本的(内存 + cpu)

  • 理解三次握手:
    服务端调用listen接口后,进入LISTEN监听状态,并同时调用accept接口,等待连接;
    第一次:客户端调用connect接口,向服务端发送SYN报文,请求连接,客户端变为SYN_SENT状态
    第二次:服务端在收到客户端建立链接请求后,向客户端发送SYN + ACK报文,建立链接并应答,服务端变为SYN_RCVD状态
    第三次:客户端在收到服务端建立链接和应答报文后,即connect接口成功返回后,向服务端回复ACK报文,客户端变为ESTABLISHED状态;服务端收到客户端应答后,即accept接口成功返回,服务端置为ESTABLISHED状态

注:

  1. 为什么是三次握手?
    由于维护链接是有成本的,如果是一次或者两次握手,客户端与服务端承受的资源损失是不一致的,客户端可以向服务端发送大量SYN请求,丢弃服务端的ACK,这样服务端会挂载大量链接,而客户端不会;
    三次握手可以嫁接同等的成本给客户端;
    三次握手也可以验证收发双方的全双工;
  2. 三次握手是否一定能够成功?
    不一定的,当客户端将第三次的ack发出的时候,客户端就置为ESTABLISHED状态,服务端是不一定能收到的;

9.TCP的断开连接(四次挥手)

在这里插入图片描述

  • 理解四次挥手:
    第一次:客户端在调用close接口关闭fd后,向服务端发送FIN报文,请求关闭连接,客户端置为FIN_WAIT_1状态
    第二次:服务器在收到客户端FIN报文后,进入CLOSE_WAIT状态,准备关闭连接,并向客户端发送ACK应答;客户端在收到ACK后,进入FIN_WAIT2状态
    第三次:服务端在处理完之前的数据后,调用close接口关闭连接,并向客户端发送FIN报文,服务端进入LAST_ACK状态,等待最后一个ACK的到来;
    第四次:客户端在收到服务端FIN报文后,进入TIME_WAIT状态,并向服务端发送ACK报文,TIME_WAIT状态会持续一段时间,之后客户端进入CLOSED状态;服务端在收到ACK报文后,彻底关闭连接,进入CLOSED状态

注:

  1. 如果发现服务端连接出现了大量的CLOSE_WAIT状态,原因是什么?
    服务端应用层代码有bug,没有关闭对应的sockfd;
  2. 四次挥手能否保证一定成功断开连接?
    不一定;
  3. 服务器可以将ACK和FIN合并在一个报文发送,因此有时也会称为三次挥手
  4. 主动断开连接的一方,其与对方的连接会进入TIME_WAIT状态一段时间;
    在这里插入图片描述
    如果服务端直接杀死进程,由于文件描述符是跟随进程的,因此该文件描述符也会关闭,连接也会断开,进入TIME_WAIT状态;
    此时,服务器维持TIME_WAIT状态是无法立即重启的,需要等待连接变成CLOSED状态;
    它的错误码是3,绑定错误
    这是因为在TIME_WAIT状态下,连接其实已经释放,但是地址信息ip、port依旧是被占用的,因此再次绑定端口是无法绑定的;
    TIME_WAIT等待时间为2 MSL(Max Segment Life,报文最大生存时间),保证历史数据从网络中消散;
    等待时间内,如果客户端发出的ACK应答丢失,对方一定会重新发送FIN报文,那么客户端就能够知道ACK丢失了,可以进行补发;
    如果对方没有重新发FIN,证明ACK一定送达了;
  5. 为什么TIME. WAIT的时间是2 MSL?
    MSL是TCP报文的最大生存时间,因此TIME_ WAIT持续存在2 MSL的话:
    ●就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启,可能会收到
    来自上一个进程的迟到的数据,但是这种数据很可能是错误的);
    ●同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失,那么服务器会再重发一个FIN,这
    时虽然客户端的进程不在了,但是TCP连接还在,仍然可以重发LAST_ ACK);
  • 服务器挂掉后需要有立即重启的能力:
    在这里插入图片描述
    使用setsockopt接口设置listensocket的属性,设置其地址复用功能,这样服务器就会绕过TIME_WAIT状态的判断,直接让其可以绑定成功;
    在这里插入图片描述
    设置地址复用后,即使服务器在TIME_WAIT期间,也可以继续绑定;
    在这里插入图片描述

10.确认应答机制 – 可靠性机制

在这里插入图片描述
只要保证A发送数据时,B都有应答,就可以保证A向B发送时的可靠性;
发出去的报文称为数据段,包括报头和数据;

  • TCP发送缓冲区:
    在这里插入图片描述
    可以将TCP的发送缓冲区看作一个char sendbuffer[NUM]的数组的结构,发送的数据段在发送缓冲区天然就有序号,序号就是数组的下标

11.超时重传机制 – 可靠性机制

当一个数据段发出后发送端主机在特定的时间间隔内没有收到该数据段的确认应答,TCP协议就会触发超时重传,再次发送该数据段;

注:

  1. 需要设定超时时间间隔,超出时间间隔若对方未回复,会进行重传;
    超时时间不能太长,也不能太短,需要根据网络状况来确认;
    TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间
    Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍;
    ●如果重发一次之后,仍然得不到应答,等待2500ms后再进行重传;
    ●如果仍然得不到应答,等待4
    500ms进行重传,依次类推,以指数形式递增;
    ●累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接;
  2. 重传有两种情况:发送的报文丢失,对方的确认应答丢失;
    在这里插入图片描述
    在这里插入图片描述

12.流量控制 – 可靠性机制

接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应;
因此TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制(Flow Control);

  • 接收端将自己可以接收的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK端通知发送端;
  • 窗口大小字段越大,说明网络的吞吐量越高;
  • 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;发送端接受到这个窗口之后,就会减慢自己的发送速度;
  • 如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端;

注:

  1. 在进行流量控制的时候,第一次发送方是如何知道接收方的接受能力的?
    第一次发送数据并不是双方第一次交换报文,在TCP三次握手的时候,双方就已经完成报文交换了,双方的窗口大小也通过报头告诉对方了;
  2. 在接收端的就收缓冲区大小有空余后,也会向发送端发送一个窗口更新通知;

13.滑动窗口 – 提高效率机制

刚才我们讨论了确认应答策略,对每一个发送的数据段都要给一个ACK确认应答,收到ACK后再发送下一个数据段;
这样做有一个比较大的缺点就是性能较差,尤其是数据往返的时间较长的时候;
在这里插入图片描述
如果我们一次并行发送多条数据段,就可以大大提高性能;
在这里插入图片描述
TCP可以并行发送多个报文,但一定要在对方主机的缓冲区接受能力内,滑动窗口机制就是用来实现这种发送策略;
在这里插入图片描述

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值;上图的窗口大小就是4000个字节(四个段);
    滑动窗口的大小 = min(拥塞窗口, 接收端窗口的大小)
  • 滑动窗口左端都是已经发送且收到应答的数据段;右端都是尚未发送的数据段;滑动窗口中的数据段可以直接发送,且暂时不需要应答;
  • 收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据;依次类推;
  • 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉;
  • 窗口越大,则网络的吞吐率就越高;
  • 滑动窗口在发送方的发送缓冲区中,属于发送缓冲区的一部分;
  • 滑动窗口的本质:发送方可以一次性向对方推送数据的上限;
  • 滑动窗口必须有上限,与对方的接受能力有关;
  • 滑动窗口机制的目的是:既想给对方推送更多的数据,又想要保证对方来得及接收;

深入理解滑动窗口:

  1. 滑动窗口其实是由两个指针维护的,在发送缓冲区中,存在两个指针win_start和win_end,这两个指针之间就是滑动窗口的内容;
    在这里插入图片描述

  2. 滑动窗口的更新策略:win_start = 收到的应答报文中的确认序号,win_end = win_start + min(拥塞窗口, 接收端窗口的大小);

  3. 滑动窗口不一定必须右移,如果接收方不取数据,那么滑动窗口左指针会右移,而右指针不动;

  4. 滑动窗口大小是可以为0的,如果对方一直不取数据,可能会导致滑动窗口大小为0;

  5. 如果没有收到滑动窗口开始报文的应答,而是收到中间报文的应答,有影响吗?
    不影响,确认应答序号的作用就是收到的确认应答序号之前的数据全部已经接收,即使前面的应答报文丢失,也可以通过后续的应答进行确认(只要发送的报文是没有丢失的);
    在这里插入图片描述

  6. 超时重传的意义:就是在发送的数据没有收到应答的时候,必须暂时保存起来;

  7. 快重传机制 – 提高效率机制
    在这里插入图片描述
    当某一段报文段丢失之后,发送端会一直收到 1001这样的ACK,就像是在提醒发送端“我想要的是1001"一样;
    如果发送端主机连续三次收到了同样一个"1001"这样的应答,就会将对应的数据1001 - 2000重新发送;
    这个时候接收端收到了1001之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中(通过报文的序号来确认是否在接收端已保存);

  8. 滑动窗口如果一直向右滑动,会不会存在越界问题?
    不会,因为TCP的发送缓冲区是环状的,相当于一个环形数组;
    在这里插入图片描述

  9. 超时重传与快重传
    两者不是对立的,是协作的,因为快重传是有条件的;两者联合起来,实现网络的高效重发;

  10. 在少量丢包的时候,采用重传机制;
    在大量丢包的时候,有可能是网络拥塞的问题,这时是绝对不能重传的,如果全部主机都重传,则会导致网络拥塞更加严重;

14.拥塞控制 – 可靠性机制

虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据,但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题;
因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵,在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引|起雪上加霜的;
TCP引入慢启动机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据;
在这里插入图片描述

  • 此处引入一个概念程为拥塞窗口
    拥塞窗口:单台主机一次向网络中发送大量数据时,可能会引发网络拥塞的上限值;只是一个整数;
  • 发送开始的时候定义拥塞窗口大小为1;
  • 每次收到一个ACK应答,拥塞窗口加1;
  • 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口;
  • 因此,滑动窗口的大小 = min(拥塞窗口, 接收端窗口的大小)

像上面这样的拥塞窗口增长速度,是指数级别的;“慢启动”只是指初使时慢,但是增长速度非常快;

  • 为了不增长的那么快,因此不能使拥塞窗口单纯的加倍;
  • 此处引入一个叫做慢启动的阈值;当拥塞窗口超过这个阈值的时候不再按照指数方式增长,而是按照线性方式增长;
    在这里插入图片描述
    当TCP开始启动的时候,慢启动阈值等于窗口最大值;
    在每次超时重发的时候慢启动阈值会变成原来的一半,同时拥塞窗口置回1;
  • 少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞;
  • 前期要让网络有一个缓一缓的机会少,慢,解决网络拥塞问题;
    中后期,网络恢复了之后,尽快恢复通信的效率;

    当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降;
    拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方但是又要避免给网络造成太大压力的折中方案;

15.延迟应答 – 提高效率机制

  • 如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小;
    假设接收端缓冲区为1M; 一次收到了500K的数据,如果立刻应答,返回的窗口就是500K;
    但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;
    在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来;
    如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M;这就是延迟应答机制

窗口越大,网络吞吐量就越大,传输效率就越高;我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;

  • 那么所有的包都可以延迟应答么?
    肯定也不是;
    数量限制:每隔N个包就应答一次;
    时间限制:超过最大延迟时间就应答一次;
    具体的数量和超时时间,依操作系统不同也有差异;一般N取2,超时时间取200ms

16.捎带应答 – 提高效率机制

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是”一发一收"的;意味着客户端给服务器说了"How are you",服务器也会给客户端回一个"Fine, thank you";
那么这个时候ACK就可以搭顺风车,和服务器回应的"Fine, thank you" 一起回给客户端;

发送应答报文的时候,有可能也会携带数据,就是将数据和应答合并了,这就是携带应答;
在这里插入图片描述

17.TCP机制总结

在这里插入图片描述

18.面向字节流

TCP协议会在内核中同时创建一个发送缓冲区和一个接收缓冲区;
发送方应用层发送数据时,只管将数据写入到自己的发送缓冲区;接收方应用层读取数据的时候,只管从自己的接收缓冲区中读取数据;
数据什么时候从发送方发送到接收方,一次发送多少数据,都是由操作系统通过TCP协议来控制的;

UDP报文发送和接收都是一对一的,一定保证接收到一个完整报文;

  • 由于缓冲区的存在,TCP程序的读和写不需要一一匹配,这就是面向字节流,例如:
    写100个字节数据时, 可以调用一次write写 100个字节,也可以调用100次write,每次写一个字节;
    读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次read 100个字节,也可以一次read一个字节,重复100次;

文件流也是一样的道理,也是字节流,数据拷贝到内核缓冲区的时候,OS是不关心写入的格式和大小,用户也不关心OS是如何刷新缓冲区的;
收发双方的读写策略都是不相关的;

19.粘包问题

首先要明确,粘包问题中的"包",是指的应用层的数据包;
在TCP的协议头中,没有如同UDP一样的“报文长度"这样的字段,但是有一个序号这样的字段;
站在传输层的角度,TCP是一个个报文过来的,按照序号排好序放在缓冲区中;
站在应用层的角度,看到的只是一-串连续的字节数据;
那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分,是一个完整的应用层数据包,这就是粘包问题;

  • 如何避免粘包问题:
    关键在于:明确两个包之间的边界;
    对于定长的包,保证每次都按固定大小读取即可;
    对于变长的包,可以在包头的位置约定一个包总长度的字段,从而就知道了包的结束位置;
    对于变长的包,还可以在包和包之间使用明确的分隔符;

20.TCP异常

  • 进程终止:进程终止会释放文件描述符(释放文件描述符就是正常四次挥手),仍然可以发送FIN,和正常关闭没有什么区别;
  • 机器重启:和进程终止的情况相同;
  • 机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行reset;即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在;如果对方不在,也会把连接释放;

21.TCP和UDP对比

  • TCP用于可靠传输的情况应用于文件传输,重要状态更新等场景;
  • UDP用于对高速传输和实时性要求较高的通信领域例如,早期的QQ,视频传输等;另外UDP可以用于广播;

22.用UDP实现可靠传输

  • 引入序列号,保证数据顺序;
  • 引入确认应答,确保对端收到了数据;
  • 引入超时重传,如果隔一段时间没有应答,就重发数据;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91420.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lv5 嵌入式开发-11 消息队列

掌握:消息队列机制、打开/创建消息队列、发送消息、接收消息 1 消息队列 消息队列是System V IPC对象的一种 消息队列由消息队列ID来唯一标识 消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等 消息队列可以按照类型来发送/接收消息 消…

Spring Boot:利用JPA进行数据库的增改

目录 JPA介绍Service接口Service和Autowired示例代码 Dao数据库操作层Repository示例代码 控制器文件示例代码-增加增加成功示例代码-修改修改成功 JPA介绍 JPA(Javaa Persistence API)一种用于持久化 Java 对象到关系型数据库的标准规范。它提供了一种统一的方式来…

Pytorch单机多卡分布式训练

Pytorch单机多卡分布式训练 数据并行: DP和DDP 这两个都是pytorch下实现多GPU训练的库,DP是pytorch以前实现的库,现在官方更推荐使用DDP,即使是单机训练也比DP快。 DataParallel(DP) 只支持单进程多线程…

openGauss学习笔记-83 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT使用内存和存储规划

文章目录 openGauss学习笔记-83 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT使用内存和存储规划83.1 MOT内存规划83.2 存储IO83.3 容量需求 openGauss学习笔记-83 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT使用内存和存储规划 本节描述了为满足特定…

完整的 pixel 6a 刷入 AOSP 源码过程记录

基础环境 虚拟机:VMware Workstation 16 Pro 16.0.0 build-16894299 Linux版本:ubuntu-16.04.7-desktop-amd64 设备:pixel 6a;代号:bluejay; 基础软件安装 安装 Git 命令:sudo apt install git …

金融生产存储亚健康治理:升级亚健康 3.0 ,应对万盘规模的挑战

随着集群规模的不断扩大,硬盘数量指数级上升,信创 CPU 和操作系统、硬盘多年老化、物理搬迁等多种复杂因素叠加,为企业的存储亚健康管理增加了新的挑战。 在亚健康 2.0 的基础上,星辰天合在 XSKY SDS V6.2 实现了亚健康 3.0&#…

【C++入门到精通】C++入门 —— set multiset (STL)

阅读导航 前言一、set简介二、std::set1. std::set简介2. std::set的使用- 基本使用- std::set的模板参数列表- std::set的构造函数- std::set的迭代器- std::set容量与元素访问函数 3. set的所有函数(表) 三、std::multiset1. std::multiset简介 四、st…

嵌入式学习笔记(35)外部中断

6.9.1什么是外部中断 (1)内部中断就是指中断源来自于SoC内部(一般是内部外设),譬如串口、定时器等部件产生的中断;外部中断是SoC外部的设备,通过外部中断对应的GPIO引脚产生的中断。 (2)按键在SoC中就使用了外部中断…

【每日一题】1498. 满足条件的子序列数目

1498. 满足条件的子序列数目 - 力扣(LeetCode) 给你一个整数数组 nums 和一个整数 target 。 请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。 由于答案可能很大,请将结果对 109 7 取余后…

stm32无人机-飞行力学原理

惯性导航,是一种无源导航,不需要向外部辐射或接收信号源,就能自主进行确定自己在什么地方的一种导航方法。 惯性导航主要由惯性器件计算实现,惯性器件包括陀螺仪和加速度计。一般来说,惯性器件与导航物体固连&#xf…

CTFSHOW SSTI

目录 web361 【无过滤】 subprocess.Popen os._wrap_close url_for lipsum cycler web362 【过滤数字】 第一个通过 计算长度来实现 第二个使用脚本输出另一个数字来绕过 使用没有数字的payload web363 【过滤引号】 使用getitem 自定义变量 web364 【过…

数据集笔记:OpenCelliD(手机基站开放数据库)

下载数据的方式可见:【数据获取】全球最大手机基站开源数据库 1 读取数据 import pandas as pdpd.read_csv(C:/Users/16000/Downloads/454.csv/454.csv,headerNone,names[Radio,MCC,MNC,LAC/TAC/NID,CID,Longitude,Latitude,Range,Samples,Changeable1,Changeable…

设计模式6、适配器模式 Adapter

解释说明:将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作 目标接口(Target):当前系统所期待的接口,它可以是抽象类或接口 适配者(Adaptee)&#xff1a…

AIGC(生成式AI)试用 7 -- 桌面小程序

生成式AI,别人用来写作,我先用来写个桌面小程序。 桌面小程序:计算器 需求 Python开发图形界面,标题:计算器 - * / 基本运算计算范围:-999999999 ~ 999999999** 乘方计算(例,2*…

LLM之Colossal-LLaMA-2:Colossal-LLaMA-2的简介、安装、使用方法之详细攻略

LLM之Colossal-LLaMA-2:Colossal-LLaMA-2的简介、安装、使用方法之详细攻略 导读:2023年9月25日,Colossal-AI团队推出了开源模型Colossal-LLaMA-2-7B-base。Colossal-LLaMA-2项目的技术细节,主要核心要点总结如下: >> 数据处…

分布式事务-TCC异常-幂等性

1、幂等性问题: 二阶段提交时,如果二阶段执行成功通知TC时出现网路或其他问题中断,那么TC没有收到执行成功的通知,TC内部有定时器不断的重试二阶段方法,导致接口出现幂等性问题。 2、解决方法 和空回滚问题一样也是…

Kotlin只截取Float小数点后数值DecimalFormat

Kotlin只截取Float小数点后数值DecimalFormat import java.text.DecimalFormatfun main(args: Array<String>) {val pi 3.141516Fvar p pi - pi.toInt()println(p)val decimalFormat DecimalFormat("00.0000")val format decimalFormat.format(p)println(…

UE5屏幕适配

一、本程序设计发布在手机上&#xff0c;首先确定屏幕的设计分辨率&#xff0c;这里我们选择iphone6s&#xff0c;750x1334。 二、设置DPI Scale为1.0的比例&#xff0c;点击齿轮标志 因为我们这个程序是手机竖屏使用的&#xff0c;所以DPI Scale Rule选择Shortest Side&#…

c语言常用语法,长时间不用容易忘。

关键字 auto 声明自动变量const 定义常量&#xff0c;如果一个变量被 const 修饰&#xff0c;那么它的值就不能再被改变extern 声明变量或函数是在其它文件或本文件的其他位置定义register 声明寄存器变量signed 声明有符号类型变量或函数static 声明静态变量&#xff0c;修饰…

APA技术架构与说明

1.自动泊车的硬件架构 2.APA自动泊车辅助系统 1&#xff09;APA主要包括以下典型功能 &#xff08;1&#xff09;泊车入库&#xff1a;利用超声波雷达或环视摄像头实现车位识别&#xff0c;并计算出合适行驶轨迹&#xff0c;对车辆进行横向/纵向控制使车辆驶入车位&#xff1…