【网络】传输层协议TCP(重点)
文章目录
- 1. TCP协议段格式
- 2. 详解TCP
- 2.1 4位首部长度
- 2.2 32位序号与32位确认序号(确认应答机制)
- 2.3 超时重传机制
- 2.4 连接管理机制(3次握手、4次挥手 + 3个标志位)
- 2.5 16位窗口大小(流量控制)
- 2.6 滑动窗口
- 2.7 3个标志位 + 16位紧急指针
- 2.8 拥塞控制
- 2.9 延迟应答
- 2.10 其它
- 2.10.1 面向字节流
- 2.10.2 粘包问题
- 2.10.3 异常情况
- 3. TCP/UDP 对比

TCP协议全称为 “传输控制协议(Transmission Control Protocol”)。
人如其名,要对数据的传输进行一个 详细的控制。
可靠性:
- 校验和
- 序列号(按序到达) (去重)
- 确认应答
- 超时重传
- 连接管理
- 流量控制
- 拥塞控制
提高性能:
- 滑动窗口
- 快重传
- 延迟应答
- 捎带应答
其他:
- 定时器(超时重传定时器, 保活定时器, TIME_WAIT 定时器等)
1. TCP协议段格式
- 16位源/目的端口号:表示数据是从哪个进程来, 到哪个进程去;
- 32位序号/32 位确认序号
- 4 位首部长度: 表示该 TCP 头部有多少个 32 位 bit(有多少个4 字节); 所以 TCP 头部最大长度是 15 * 4 = 60
- 6 位标志位:
- ACK:确认号是否有效
- SYN:请求建立连接;我们把携带 SYN 标识的称为同步报文段
- FIN:通知对方, 本端要关闭了, 我们称携带 FIN 标识的为结束报文段
- PSH: 提示接收端应用程序立刻从 TCP 缓冲区把数据读走
- RST:对方要求重新建立连接; 我们把携带 RST标识的称为复位报文段
- URG:紧急指针是否有效
- 16 位窗口大小
- 16 位校验和:发送端填充,CRC 校验。接收端校验不通过,则认为数据有问题,此处的检验和不光包含 TCP 首部,也包含TCP 数据部分.
- 16 位紧急指针:标识哪部分数据是紧急数据;
- 40 字节头部选项:暂时忽略
下面的是Linux源代码中,tcp报头的定义:
struct tcphdr {__be16 source; // 源端口号__be16 dest; // 目的端口号__be32 seq; // 序列号__be32 ack_seq; // 确认号
#if defined(__LITTLE_ENDIAN_BITFIELD)//使用了位段__u16 res1:4, // 保留位doff:4, // 数据偏移(头部长度,以32位字为单位)fin:1, // FIN标志:结束连接syn:1, // SYN标志:同步序列号rst:1, // RST标志:重置连接psh:1, // PSH标志:Push函数ack:1, // ACK标志:确认字段有效urg:1, // URG标志:紧急指针字段有效ece:1, // ECN回显标志cwr:1; // 拥塞窗口减少标志
#elif defined(__BIG_ENDIAN_BITFIELD)__u16 doff:4, // 数据偏移(头部长度,以32位字为单位)res1:4, // 保留位cwr:1, // 拥塞窗口减少标志ece:1, // ECN回显标志urg:1, // URG标志:紧急指针字段有效ack:1, // ACK标志:确认字段有效psh:1, // PSH标志:Push函数rst:1, // RST标志:重置连接syn:1, // SYN标志:同步序列号fin:1; // FIN标志:结束连接
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif__be16 window; // 窗口大小__sum16 check; // 校验和__be16 urg_ptr; // 紧急指针
};
2. 详解TCP
2.1 4位首部长度
4位首部长度
= 标准报头长度 + 选项长度,单位是4字节。
4个比特位可表示的范围是 [0,15],可表示的大小就是 [0,60]字节,由于标准报头占 20 字节,所以4位首部长度的范围是 [20,60]。
所以,TCP解包时,先读取报文的前20字节,然后再根据4位首部长度,将报头+选项提取出来,剩下的就是有效载荷的长度。
2.2 32位序号与32位确认序号(确认应答机制)
首先我们要知道,32位序号是用来保证收到的报文的可靠性的(对历史报文的可靠性)。
TCP中的可靠性主要是依靠确认应答实现的,否则发送方不知道自己发送的报文是否被收到了。
只要发送端收到了应答,说明发送的数据一定被收到了,可靠性也就保证了。(接收端无需关心自己的应答是否可靠,如果不可靠,发送端会重发数据;如果可靠,发送端就发新的数据了)
那什么是确认呢?
确认,至少是一个“裸”的tcp报头
32位序号又是什么呢?
根据我们上面所说的,一条请求对应一条应答,没有收到应答就会重新发送请求;如果是串行的话,效率就太低了,所以TCP选择的是并行发送。
并行发送会存在一个问题,不知道应答对应哪一条请求,所以必须对请求编号,这个编号就是32位序号
32位确认序号就是对报文的序号+1,表示序号之前的内容已经收到了。
(序号与确认序号不一定是一对一的,多个序号可能只会有一条确认序号,表示该序号之前的内容已全部收到)
序号存在的另一个原因:保证报文的按序到达
报文如果到达后是乱序的,这也是不可靠的的表现,所以可以根据序号排序,然后按顺序入缓冲区。
可是报头中为什么要有两个32位序号呢?一个也够用呀?
两个32位序号,是为了实现捎带应答机制。接收端应答的同时,也想捎带着给发送端发送数据。
所以,TCP报文在很大概率上,既是应答,也是数据。
那序号又是如何产生的呢?
2.3 超时重传机制
主机 A 发送数据给 B 之后,可能因为网络拥堵等原因,数据无法到达主机 B;如果主机 A 在一个特定时间间隔内没有收到 B 发来的确认应答,就会进行重发;
但是,主机 A 未收到 B 发来的确认应答, 也可能是因为应答丢失了
因此主机 B 会收到很多重复数据。那么 TCP 协议需要能够识别出那些包是重复的包, 并且把重复的丢弃掉。
这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果。
所以,为了降低重复率,不能让发送方一直发,需要设定一个时间,超过这个时间后,发送端再发,这种机制叫做超时重传机制。
那超时的时间如何确定呢?
- 最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返回”。
- 但是这个时间的长短,随着网络环境的不同,是有差异的。 如果超时时间设的太长,会影响整体的重传效;如果超时时间设的太短,有可能会频繁发送重复的包。
TCP 为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间
Linux 中(BSD Unix 和 Windows 也是如此),超时以 500ms 为一个单位进行控制
,每次判定超时重发的超时时间都是 500ms 的整数倍。
- 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传。
- 如果仍然得不到应答,等待 4*500ms 进行重传, 依次类推, 以指数形式递增。
- 累计到一定的重传次数, TCP 认为网络或者对端主机出现异常,强制关闭连接。
2.4 连接管理机制(3次握手、4次挥手 + 3个标志位)
在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接。
在正式学习握手、挥手之前,先了解报头中的几个标志位。
在TCP报头中,有6个标志位,用来区分接收端收到的TCP报文的类型 (可能有多个发送端)。
- ACK:acknowledgement
表明自己是一个确认报文,让对方关心确认序号。 (因为有捎带应答机制,所以大部分的TCP报文的ACK标志位都为1)
- SYN:synchronize
同步标志位,即表明是一个建立连接的请求
- FIN:finish
表明自己是一个断开连接的请求,一般用于通信结束时。
双方建立连接,首先要进行3次握手
举个栗子:
男:你愿意做我女朋友吗?
女:好呀,什么时候开始?
男:就现在!
在上面的例子中,双方用了最小的握手次数,建立了关系,这就叫做三次握手
双方断开连接,首先要进行4次挥手
举个栗子:
女:我们分手吧!
男:好!
男:我也要跟你分手!
女:好!
为什么叫做四次挥手? - 因为断开连接需要征得双方的同意
! (因为TCP是全双工的,要关闭两个朝向上的连接)
3次握手,是由操作系统自动完成的。
服务器端:accept返回后,连接已经建立完成了。即accept等3次握手完成,它不参与3次握手
。
客户端:connect调用后,触发操作系统,让操作系统发送SYN
,双方握手完成,connect返回。
- 只要客户端发出去SYN,它的状态就变成了
SYN_SENT
;客户端发出去ACK,就认为自己把连接建立好了,状态变为established。(客户端不保证发送的ACK一定能被收到,所以3次握手本质就是在赌,因为3次握手本来就不一定成功)
- 服务端未收到ACK,但发送端以为连接建立成功了,发送端此时就会发送数据,但是服务端不认识它,会通过标志位RST要求重新建立连接。
- 一般服务端只要收到了SYN,它的状态就变成SYN_RECV;它收到客户端的ACK后,才认为连接建立完成。
- 所以,一般是客户端认为连接先建立好。
有了四次挥手的理解,3次握手的本质,其实也是四次握手!
所以,为什么要3次握手呢?
- 建立连接,要征得双方的同意;因为TCP是全双工的,要建立两个朝向上的连接
- 在3次握手期间,正式通信之前,双方验证了全双工信道的通畅性(客户端与服务端的IO是正常的,即网络是通畅的)
谈了这么多,到底什么是连接呢?
- 一条连接,一定会和一个文件对应;因为一个连接,对应一个文件描述符。
- 那么,连接在操作系统内就会存在很多个,操作系统一定要管理连接。先描述在组织,创建连接的struct,在struct内部,一定会有一个字段来表示连接的状态。
下面我们再来看一下4次挥手
介绍一个系统调用,shutdown
可控制关闭连接的读写端
我们具体是使用close还是shutdown,取决于应用层。
在服务器这边,如果不调用close关闭sockfd,那就只会进行两次挥手,server会一直处于close_wait状态,会造成文件描述符泄漏、内存泄漏问题。
当服务器关闭后,server会进入last_ack状态,可是此时客户端早就关闭了,没人给它应答了,那么服务端在一段时间后,自动进入closed状态。
那客户端的time_wait状态是什么意思呢??
- 在四次挥手时,主动断开连接的一方会进入time_wait状态,要等待一个
2MSL(Max Segment Life,报文最大生存时间)
,才会进入 CLOSED 状态为什么会这样呢?举个例子:
- 在有些情况下,双方都关闭后,接收端重启并与发送端建立连接后,发送方被判定为超时的报文可能又到达了。为了防止报文被接收端误处理,发送方需要等待2MSL后才可再次启动。
等待2MSL的目的是:
- 等待历史的游离报文,在网络中消散!
- 若time_wait状态下的ACK丢了,那么就可以以最快的速度重新发送,尽可能正常的完成4次挥手断开连接
为什么是2MSL呢?MSL不行吗?
- 理想情况下,1个MSL时间足以确保一个报文在网络中消散
- 报文在网络中传输时,会经历各种延迟,包括路由器处理延迟、链路传输延迟等。这些延迟是不确定的,可能会导致报文在较长时间内仍然存在于网络中。
- 等待2MSL时间可以确保旧连接的所有报文(包括丢失的报文和重传的报文)在网络中完全消失。
- 假设MSL为30秒:
- 丢失的报文:一个报文在接近30秒时丢失。
- 重传的报文:发送方在超时后(假设超时时间为1秒)重传该报文,重传的报文也会在网络中传输,其生存时间也是30秒。
总时间:因此,最坏情况下,报文的总生存时间是30秒(丢失的报文)+ 30秒(重传的报文)= 60秒。- 如果ACK报文丢失,被动关闭方重传的FIN报文也需要在网络中传输,这同样需要一个MSL时间。因此,总共需要2MSL时间来确保ACK报文的可靠传输和FIN报文的重传处理。
在我们前面写代码时,端口号绑定失败的原因:
- 当服务端主动关闭后,其进入time_wait状态,即进程没有退出,端口号被占用了。
- 若想使用旧端口号,可以通过系统调用
setsockopt()
设置套接字的类型
可以通过 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看 msl 的值
2.5 16位窗口大小(流量控制)
接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应,不做任何处理则会浪费了各种资源(网络带宽、CPU等等)。
因此 TCP 支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制。
接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段
- 窗口大小字段越大, 说明网络的吞吐量越高,发送端接受到这个窗口之后, 就会提高自己的发送速度
- 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端;发送端接受到这个窗口之后, 就会减慢自己的发送速度;
- 如果接收端缓冲区满了,就会将窗口置为 0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。
- 双方都要进行流量控制
- 首次发送如何知道对方的接收能力呢? 三次握手时,是做过报文交换与窗口协商的!
接收端如何把窗口大小告诉发送端呢? TCP 首部中,有一个 16 位窗口大小字段,就是存放了窗口大小信息(即自己接收缓冲区中剩余空间的大小);
那么问题来了,16 位数字最大表示 65535, 那么 TCP 窗口最大就是 65535 字节么?
实际上,TCP 首部 40 字节选项中还包含了一个窗口扩大因子 M,实际窗口大小是窗口字段的值左移 M 位;
2.6 滑动窗口
在我们讨论了确认应答策略时, 对每一个发送的数据段,都要给一个 ACK 确认应答,收到 ACK 后再发送下一个数据段(串行发送)。
这样做有一个比较大的缺点:就是性能较差,尤其是数据往返的时间较长的时候。
我们说TCP是采用并行发送的,它是怎么实现的呢?流量控制又是怎么实现的呢? - - 滑动窗口
窗口大小指的是:无需等待确认应答就可以继续发送数据的最大值。 下图的窗口大小就是 4000 个字节(四个段)
- 发送前四个段的时候, 不需要等待任何 ACK, 直接发送;
- 收到第一个 ACK 后, 滑动窗口向后移动(start = ACK),继续发送第五个段的数据(end = start + 16位窗口大小),依次类推;
- 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉
- 窗口越大,则网络的吞吐率就越高;窗口越小,网络的吞吐率越低。(流量控制)
此时就是并行发送的了
那么如果出现了丢包,如何进行重传?这里分两种情况讨论:
- 情况一: 数据包已经抵达, ACK 被丢了
这种情况下, 部分 ACK 丢了并不要紧,因为可以通过后续的 ACK 进行确认;
- 情况二:数据包就直接丢了
当某一段报文段丢失之后,发送端会一直收到 1001 这样的 ACK,就像是在提醒发送端 “我想要的是 1001” 一样,滑动窗口会先向右移动到已经发送成功处,然后补发丢失的报文。
- 如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数 据 1001 - 2000 重新发送;
- 这个时候接收端收到了 1001 之后, 再次返回的 ACK 就是 7001 了(因为 2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中 ,这种机制被称为 “高速重发控制”(也叫 "快重传).
既然有了快重传,它既快,又能重传,那为什么还要超时重传呢?
快重传是有条件的:要连续三次收到同一个应答!
万一发送方只发送了2个报文呢?最多就只能收到2个应答呗,那就无法触发快重传,只能超时重传。所以,超时重传是兜底的;快重传是提高效率的
。
2.7 3个标志位 + 16位紧急指针
有了上面的理解,我们来了解一下TCP报头中剩余的3个标志位
- PSH:push
在进行流量控制时,如果接收方的缓冲区已满,那发送方也就只能发送探测报文,没有别的办法了。
为了告诉对方,请尽快将缓冲区中的数据交给上层,就引入了PSH标志位;也可利用PSH标志位,告诉对端,我的数据比较重要,请尽快交付。
- RST:reset
重置连接(重新三次握手)
在三次握手时,服务端未收到ACK,但发送端以为连接建立成功了,发送端此时就会发送数据,但是服务端不认识它,会通过标志位RST要求重新建立连接。
- URG:urgent
表示紧急报文,优先让上层从缓冲区中读取。
那紧急数据在哪里呢?
在TCP报头中,有16位紧急指针,表示紧急数据在有效载荷中的偏移量,通过它就可以获取紧急数据。
但是只有紧急数据的起始地址,紧急数据有多长呢?
TCP允许插队,但不允许过度插队, 紧急数据只占一个字节! 以后可以在紧急数据中设置状态码(如终止连接、暂停上传等等)
在系统调用
recv
中,可以设置标志位MSG_OOB
,来读取紧急数据。
2.8 拥塞控制
虽然 TCP 有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据,但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题。
因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。 所以TCP使用拥塞控制来考虑网络的健康状况, 一旦发送的报文大量丢失,则会被判定为网络拥塞。
大量报文丢失后,能不能直接重传呢?- - - 不能,因为可能会造成网络更加的拥堵!应该等一等
TCP 引入慢启动机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。
此处引入一个拥塞窗口
的概念,拥塞窗口是衡量网络拥堵的指标。
- 发送开始的时候,定义拥塞窗口大小为 1
- 每次收到一个 ACK 应答,拥塞窗口加 1 倍
滑动窗口 = min (拥塞窗口,对端接收缓冲区剩余空间的大小)
像上面这样的拥塞窗口增长速度,是指数级别的。“慢启动” 只是指初使时慢,但是增长速度非常快 (指数级增长)。
可是为什么使用指数级增长呢?
指数增长的特点是:前期慢,后期快;既然前面慢速度发送的都没有问题,那就应该尽快进行网络的恢复。
但是,为了不增长的那么快,不能使拥塞窗口单纯的加倍;此处引入一个叫做慢启动的阈值,当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长
拥塞控制算法 = 慢启动 + 加法增大 + 乘法减小
可是这个拥塞窗口为什么一直在试探性的增大呢?
拥塞窗口是网络健康状况的评估值,网络的状况是一直在变化的,所以要反复的试探,尽量让下一次的阈值高一点。
拥塞控制,归根结底是 TCP 协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。
2.9 延迟应答
接收端收到数据后,如果接收数据的主机立刻返回 ACK 应答,这时候返回的窗口可能比较小(上层未取走刚接收到的报文)
- 假设接收端缓冲区为 1M,一次收到了 500K 的数据,如果立刻应答,返回的窗口就是 500K;
- 但实际上可能处理端处理的速度很快, 10ms 之内就把 500K 数据从缓冲区消费掉了;在这种情况下,接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;
- 如果接收端稍微等一会再应答,比如等待 200ms 再应答, 那么这个时候返回的窗口大小就是 1M;
- 一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高。我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;
那么所有的包都可以延迟应答么? 肯定也不是
- 数量限制: 每隔 N 个包就应答一次;
- 时间限制: 超过最大延迟时间就应答一次;
- 具体的数量和超时时间,依操作系统不同也有差异;一般 N 取 2,超时时间取 200ms;
2.10 其它
2.10.1 面向字节流
创建一个 TCP 的 socket,同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区
- 调用 write 时, 数据会先写入发送缓冲区中; 如果发送的字节数太长,会被拆分成多个 TCP 的数据包发出;
- 如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适的时机发送出去;
- 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区;然后应用程序可以调用 read 从接收缓冲区拿数据;
- 另一方面,TCP 的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据,这个概念叫做全双工
由于缓冲区的存在, TCP 程序的读和写不需要一一匹配,例如:
- 写 100 个字节数据时,可以调用一次 write 写 100 个字节, 也可以调用 100 次write,每次写一个字节;
- 读 100 个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次read 100 个字节, 也可以一次 read 一个字节,重复 100 次
- 具体传输的数据是什么,由上层解释。
2.10.2 粘包问题
首先要明确,粘包问题中的 “包” ,是指的应用层的数据包。
- 在 TCP 的协议头中,没有如同 UDP 一样的 “报文长度” 这样的字段, 但是有一个序号这样的字段
- 站在传输层的角度,TCP 是一个一个报文过来的,按照序号排好序放在缓冲区中
- 站在应用层的角度,看到的只是一串连续的字节数据
- 那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始,到哪个部分是一个完整的应用层数据包
那么如何避免粘包问题呢? 归根结底就是一句话,明确两个包之间的边界
- 对于定长的包,保证每次都按固定大小读取即可;那么就从缓冲区从头开始按固定大小依次读取即可;
- 对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;
- 对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定的,只要保证分隔符不和正文冲突即可)
思考: 对于 UDP 协议来说,是否也存在 “粘包问题” 呢?
- 对于 UDP,如果还没有给上层交付数据,UDP 的报文长度仍然在;同时,UDP 是一个一个把数据交付给应用层,就有很明确的数据边界.
- 站在应用层的站在应用层的角度,使用 UDP 的时候, 要么收到完整的 UDP 报文,要么不收,不会出现"半个"的情况
2.10.3 异常情况
- 进程终止:进程终止会释放文件描述符,仍然可以发送 FIN,和正常关闭没有什么区别
- 机器重启:和进程终止的情况相同.
- 机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行 reset。即使没有写入操作, TCP 自己也内置了一个保活定时器,会定期询问对方是否还在,如果对方不在,也会把连接释放 - - - 连接保活机制。
- 应用层的某些协议,也有一些这样的检测机制。例如 HTTP 长连接中,也会定期检测对方的状态。例如 QQ在 QQ 断线之后,也会定期尝试重新连接
3. TCP/UDP 对比
- TCP/UDP 对比
我们说了 TCP 是可靠连接,那么是不是 TCP 一定就优于 UDP 呢? TCP 和 UDP 之间的优点和缺点。不能简单、绝对的进行比较
- TCP 用于可靠传输的情况,应用于文件传输,重要状态更新等场景
- UDP 用于对高速传输和实时性要求较高的通信领域,例如,早期的 QQ、视频传输等;另外 UDP 可以用于广播;
归根结底,TCP 和 UDP 都是程序员的工具,什么时机用,具体怎么用,还是要根据具体的需求场景去判定
- 基于 TCP 应用层协议
- HTTP
- HTTPS
- SSH
- Telnet
- FTP
- SMTP
- 用 UDP 实现可靠传输(经典面试题)
先根据应用场景,确定具体的应用需求,可靠性要保障到什么程度;再参考 TCP 的可靠性机制, 在应用层实现类似的逻辑;
- 例如:
- 引入序列号, 保证数据顺序;
- 引入确认应答, 确保对端收到了数据;
- 引入超时重传, 如果隔一段时间没有应答, 就重发数据;
- …
相关文章:
【网络】传输层协议TCP(重点)
文章目录 1. TCP协议段格式2. 详解TCP2.1 4位首部长度2.2 32位序号与32位确认序号(确认应答机制)2.3 超时重传机制2.4 连接管理机制(3次握手、4次挥手 3个标志位)2.5 16位窗口大小(流量控制)2.6 滑动窗口2.7 3个标志位 16位紧急…...
17.[前端开发]Day17-形变-动画-vertical-align
1 transform CSS属性 - transform transform的用法 表示一个或者多个 不用记住全部的函数,只用掌握这四个常用的函数即可 位移 - translate <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta ht…...
LeetCode435周赛T2贪心
题目描述 给你一个由字符 N、S、E 和 W 组成的字符串 s,其中 s[i] 表示在无限网格中的移动操作: N:向北移动 1 个单位。S:向南移动 1 个单位。E:向东移动 1 个单位。W:向西移动 1 个单位。 初始时&#…...
陆游的《诗人苦学说》:从藻绘到“功夫在诗外”(中英双语)mastery lies beyond poetry
陆游的《诗人苦学说》:从藻绘到“功夫在诗外” 今天看万维钢的《万万没想到》一书,看到陆游的功夫在诗外的句子,特意去查找这首诗的原文。故而有此文。 我国学人还往往过分强调“功夫在诗外”这句陆游的名言,认为提升综合素质是一…...
AI模型平台之——ModelScope(魔搭)
ModelScope 是什么? ModelScope 是一个由阿里巴巴达摩院推出的开源模型库和工具集,旨在为开发者提供高效、便捷的机器学习模型和工具。ModelScope 提供了丰富的预训练模型、数据集和工具,支持多种任务和应用场景,如自然语言处理、…...
GIt使用笔记大全
Git 使用笔记大全 1. 安装 Git 在终端或命令提示符中,输入以下命令检查是否已安装 Git: git --version如果未安装,可以从 Git 官方网站 下载并安装适合你操作系统的版本。 2. 配置 Git 首次使用 Git 时,需要配置用户名和邮箱…...
42【文件名的编码规则】
我们在学习的过程中,写出数据或读取数据时需要考虑编码类型 火山采用:UTF-16 易语言采用:GBK php采用:UTF-8 那么我们写出的文件名应该是何种编码的?比如火山程序向本地写出一个“测试.txt”,理论上这个“测…...
Linux网络 HTTPS 协议原理
概念 HTTPS 也是一个应用层协议,不过 是在 HTTP 协议的基础上引入了一个加密层。因为 HTTP的内容是明文传输的,明文数据会经过路由器、wifi 热点、通信服务运营商、代理服务器等多个物理节点,如果信息在传输过程中被劫持,传输的…...
Vue.js组件开发-实现全屏手风琴幻灯片切换特效
使用 Vue 实现全屏手风琴幻灯片切换特效 步骤概述 创建 Vue 项目:使用 Vue CLI 创建一个新的 Vue 项目。设计组件结构:创建一个手风琴幻灯片组件,包含幻灯片项和切换逻辑。实现样式:使用 CSS 实现全屏和手风琴效果。添加交互逻辑…...
数据库、数据仓库、数据湖有什么不同
数据库、数据仓库和数据湖是三种不同的数据存储和管理技术,它们在用途、设计目标、数据处理方式以及适用场景上存在显著差异。以下将从多个角度详细说明它们之间的区别: 1. 数据结构与存储方式 数据库: 数据库主要用于存储结构化的数据&…...
MLM之MiniCPM-o:MiniCPM-o的简介(涉及MiniCPM-o 2.6和MiniCPM-V 2.6)、安装和使用方法、案例应用之详细攻略
MLM之MiniCPM-o:MiniCPM-o的简介(涉及MiniCPM-o 2.6和MiniCPM-V 2.6)、安装和使用方法、案例应用之详细攻略 目录 MiniCPM-o的简介 0、更新日志 1、MiniCPM-o系列模型特点 MiniCPM-o 2.6 的主要特点 MiniCPM-V 2.6的主要特点 2、MiniCPM-o系列模型架构 MiniC…...
【Conda 和 虚拟环境详细指南】
Conda 和 虚拟环境的详细指南 什么是 Conda? Conda 是一个开源的包管理和环境管理系统,支持多种编程语言(如Python、R等),最初由Continuum Analytics开发。 主要功能: 包管理:安装、更新、删…...
Rust 控制流语法详解
Rust 控制流语法详解 控制流是编程语言中用于控制代码执行顺序的重要机制。Rust 提供了多种控制流语法,包括条件判断(if、else if)、循环(loop、while、for)等。本文将详细介绍这些语法,并通过示例展示它们…...
VLC-Qt: Qt + libVLC 的开源库
参考链接 https://blog.csdn.net/u012532263/article/details/102737874...
洛谷 P5146 最大差值 C语言
P5146 最大差值 - 洛谷 | 计算机科学教育新生态 题目描述 HKE 最近热衷于研究序列,有一次他发现了一个有趣的问题: 对于一个序列 A1,A2,…,An,找出两个数 i,j(1≤i<j≤n),使得 Aj−Ai 最大。…...
Zabbix 推送告警 消息模板 美化(钉钉Webhook机器人、邮件)
目前网络上已经有很多关于Zabbix如何推送告警信息到钉钉机器人、到邮件等文章。 但是在搜索下来,发现缺少了对告警信息的美化的文章。 本文不赘述如何对Zabbix对接钉钉、对接邮件,仅介绍我采用的美化消息模板的内容。 活用AI工具可以减轻很多学习、脑力负…...
MySQL数据库环境搭建
下载MySQL 官网:https://downloads.mysql.com/archives/installer/ 下载社区版就行了。 安装流程 看b站大佬的视频吧:https://www.bilibili.com/video/BV12q4y1477i/?spm_id_from333.337.search-card.all.click&vd_source37dfd298d2133f3e1f3e3c…...
书生大模型实战营7
文章目录 L1——基础岛提示词工程实践什么是Prompt(提示词)什么是提示工程提示设计框架CRISPECO-STAR LangGPT结构化提示词LangGPT结构编写技巧构建全局思维链保持上下文语义一致性有机结合其他 Prompt 技巧 常用的提示词模块 浦语提示词工程实践(LangGPT版)自动化生成LangGPT提…...
Spark的基本概念
个人博客地址:Spark的基本概念 | 一张假钞的真实世界 编程接口 RDD:弹性分布式数据集(Resilient Distributed Dataset )。Spark2.0之前的编程接口。Spark2.0之后以不再推荐使用,而是被Dataset替代。Datasetÿ…...
langchain基础(二)
一、输出解析器(Output Parser) 作用:(1)让模型按照指定的格式输出; (2)解析模型输出,提取所需的信息 1、逗号分隔列表 CommaSeparatedListOutputParser:…...
读取要素类中的几何信息
在arcpy中,每个要素都有相关的集合对象,都可以在游标中访问.本节将使用SearchCursor和Polyon对象来读取面要素类几何信息. 操作方法 1.打开IDLE,新建一个脚本 2.导入arcpy模块 3.设置输入要素类为目标面要素类 infc "<>" 4.传入输入要素类创建SearchCurs…...
洛谷 P1130 红牌 C语言
题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂,一共包括 N 个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程,每一步政府都派了 M 个工作人员来检查材料。不幸的是&…...
五. Redis 配置内容(详细配置说明)
五. Redis 配置内容(详细配置说明) 文章目录 五. Redis 配置内容(详细配置说明)1. Units 单位配置2. INCLUDES (包含)配置3. NETWORK (网络)配置3.1 bind(配置访问内容)3.2 protected-mode (保护模式)3.3 port(端口)配置3.4 timeout(客户端超时时间)配置3.5 tcp-keepalive()配置…...
LeetCode题练习与总结:有效三角形的个数--611
一、题目描述 给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。 示例 1: 输入: nums [2,2,3,4] 输出: 3 解释:有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3示例 2: 输入: nums [4,2,3,4] 输出: 4 提示: 1 &…...
【multi-agent-system】ubuntu24.04 安装uv python包管理器及安装依赖
uv包管理器是跨平台的 参考sudo apt-get update sudo apt-get install -y build-essential我的开发环境是ubuntu24.04 (base) root@k8s-master-pfsrv:/home/zhangbin/perfwork/01_ai/08_multi-agent-system# uv venv 找不到命令 “uv”,但可以通过以下软件...
【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现
文章目录 介绍Transformer核心组件架构图编码器(Encoder)解码器(Decoder) 优点应用代码实现导包基于位置的前馈网络残差连接后进行层规范化编码器 Block编码器解码器 Block解码器训练预测 个人主页:道友老李 欢迎加入社…...
STM32单片机学习记录(2.2)
一、STM32 13.1 - PWR简介 1. PWR(Power Control)电源控制 (1)PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能; (2)可编程电压监测器(…...
毕业设计:基于卷积神经网络的鲜花花卉种类检测算法研究
目录 前言 课题背景和意义 实现技术思路 一、算法理论基础 1.1 卷积神经网络 1.2目标检测算法 二、 数据集 2.1 数据集 2.2 数据扩充 三、实验及结果分析 3.1 实验环境搭建 3.2 模型训练 最后 前言 📅大四是整个大学期间最忙碌的时光,一边要忙着备考或…...
DeepSeek-R1模型1.5b、7b、8b、14b、32b、70b和671b有啥区别?
deepseek-r1的1.5b、7b、8b、14b、32b、70b和671b有啥区别?码笔记mabiji.com分享:1.5B、7B、8B、14B、32B、70B是蒸馏后的小模型,671B是基础大模型,它们的区别主要体现在参数规模、模型容量、性能表现、准确性、训练成本、推理成本…...
云原生(五十三) | SQL查询操作
文章目录 SQL查询操作 一、数据库DDL操作 1、登陆数据库 2、创建DB数据库 二、数据表DDL操作 1、创建数据表 2、RDS中SQL查询操作 三、SQL查询操作 1、RDS中SQL查询操作 SQL查询操作 一、数据库DDL操作 1、登陆数据库 2、创建DB数据库 创建一个普通账号,…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_strerror_init()函数
目录 ngx_strerror_init()函数声明 ngx_int_t 类型声明定义 intptr_t 类型 ngx_strerror_init()函数实现 NGX_HAVE_STRERRORDESC_NP ngx_strerror_init()函数声明 在 nginx.c 的开头引入了: #include <ngx_core.h> 在 ngx_core.h 中引入了 #include <ngx_er…...
【HTML入门】Sublime Text 4与 Phpstorm
文章目录 前言一、环境基础1.Sublime Text 42.Phpstorm(1)安装(2)启动Phpstorm(3)“启动”码 二、HTML1.HTML简介(1)什么是HTML(2)HTML版本及历史(3)HTML基本结构 2.HTML简单语法(1)HTML标签语法(2)HTML常用标签(3)表格(4)特殊字符 总结 前言 在当今的软件开发领域,…...
亲和传播聚类算法应用(Affinity Propagation)
亲和传播聚类算法应用(Affinity Propagation) 亲和传播(Affinity Propagation,简称 AP)是一种基于“消息传递”的聚类算法,与 K-Means 等传统聚类方法不同,它不需要用户预先指定簇的数量&#…...
【VM】VirtualBox安装CentOS8虚拟机
阅读本文前,请先根据 VirtualBox软件安装教程 安装VirtualBox虚拟机软件。 1. 下载centos8系统iso镜像 可以去两个地方下载,推荐跟随本文的操作用阿里云的镜像 centos官网:https://www.centos.org/download/阿里云镜像:http://…...
pytorch实现文本摘要
人工智能例子汇总:AI常见的算法和例子-CSDN博客 import numpy as npfrom modelscope.hub.snapshot_download import snapshot_download from transformers import BertTokenizer, BertModel import torch# 下载模型到本地目录 model_dir snapshot_download(tians…...
大数据相关职位介绍之一(数据分析,数据开发,数据产品经理,数据运营)
大数据相关职位介绍之一 随着大数据、人工智能(AI)和机器学习的快速发展,数据分析与管理已经成为各行各业的重要组成部分。从互联网公司到传统行业的数字转型,数据相关职位在中国日益成为推动企业创新和提升竞争力的关键力量。以…...
Vue3.0实战:大数据平台可视化(附完整项目源码)
文章目录 创建vue3.0项目项目初始化项目分辨率响应式设置项目顶部信息条创建页面主体创建全局引入echarts和axios后台接口创建express销售总量图实现完整项目下载项目任何问题都可在评论区,或者直接私信即可。 创建vue3.0项目 创建项目: vue create vueecharts选择第三项:…...
多模态论文笔记——NaViT
大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本文详细解读多模态论文NaViT(Native Resolution ViT),将来自不同图像的多个patches打包成一个单一序列——称为Patch n’ Pack—…...
AI大模型开发原理篇-5:循环神经网络RNN
神经概率语言模型NPLM也存在一些明显的不足之处:模型结构简单,窗口大小固定,缺乏长距离依赖捕捉,训练效率低,词汇表固定等。为了解决这些问题,研究人员提出了一些更先进的神经网络语言模型,如循环神经网络、…...
无人机图传模块 wfb-ng openipc-fpv,4G
openipc 的定位是为各种模块提供底层的驱动和linux最小系统,openipc 是采用buildroot系统编译而成,因此二次开发能力有点麻烦。为啥openipc 会用于无人机图传呢?因为openipc可以将现有的网络摄像头ip-camera模块直接利用起来,从而…...
C++ Primer 自定义数据结构
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
Kanass快速安装配置教程(入门级)
Kanass是一款国产开源免费的项目管理工具,工具简洁易用、开源免费,本文将介绍如何快速安装配置kanass,以快速上手。 1、快速安装 1.1 Linux 安装 点击官网 -> 演示与下载 ->下载,下载Linux安装包,…...
【自然语言处理(NLP)】基于Transformer架构的预训练语言模型:BERT 训练之数据集处理、训练代码实现
文章目录 介绍BERT 训练之数据集处理BERT 原理及模型代码实现数据集处理导包加载数据生成下一句预测任务的数据从段落中获取nsp数据生成遮蔽语言模型任务的数据从token中获取mlm数据将文本转换为预训练数据集创建Dataset加载WikiText-2数据集 BERT 训练代码实现导包加载数据构建…...
深度解析:网站快速收录与网站安全性的关系
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/58.html 网站快速收录与网站安全性之间存在着密切的关系。以下是对这一关系的深度解析: 一、网站安全性对收录的影响 搜索引擎惩罚: 如果一个网站存在安全隐患&am…...
《基于Scapy的综合性网络扫描与通信工具集解析》
在网络管理和安全评估中,网络扫描和通信是两个至关重要的环节。Python 的 Scapy 库因其强大的网络数据包处理能力,成为开发和实现这些功能的理想工具。本文将介绍一个基于 Scapy 编写的 Python 脚本,该脚本集成了 ARP 扫描、端口扫描以及 TCP…...
MySQL索引详解
MySQL索引详解 什么是索引索引的原理索引的分类索引的数据结构二叉树平衡二叉树B树B树 聚集索引与非聚集索引概念利用聚集索引查找数据利用非聚集索引查找数据覆盖索引与回表操作 如何正确使用索引 什么是索引 索引是存储引擎中一种数据结构,或者说数据的组织方式&…...
【NEXT】网络编程——上传文件(不限于jpg/png/pdf/txt/doc等),或请求参数值是file类型时,调用在线服务接口
最近在使用华为AI平台ModelArts训练自己的图像识别模型,并部署了在线服务接口。供给客户端(如:鸿蒙APP/元服务)调用。 import核心能力: import { http } from kit.NetworkKit; import { fileIo } from kit.CoreFileK…...
【Qt】界面优化
界面优化 设置全局样式样式文件使⽤ Qt Designer 编辑样式选择器设置子控件样式伪类选择器样式属性盒模型设置按钮样式设置复选框样式输入框样式列表样式菜单栏样式 在 Qt 中对界面的优化和 CSS 类似。语法结构如下: 选择器 {属性名: 属性值; }例如: QP…...
机器学习算法在网络安全中的实践
机器学习算法在网络安全中的实践 本文将深入探讨机器学习算法在网络安全领域的应用实践,包括基本概念、常见算法及其应用案例,从而帮助程序员更好地理解和应用这一领域的技术。"> 序言 网络安全一直是信息技术领域的重要议题,随着互联…...
课题介绍:基于惯性与单目视觉信息融合的室内微小型飞行器智能自主导航研究
室内微小型飞行器在国防、物流和监测等领域中应用广泛,但在复杂的非合作环境中实时避障和导航仍面临诸多挑战。由于微小型飞行器的载荷和能源限制,迫切需要开发高效的智能自主导航系统。本项目旨在研究基于惯性导航与单目视觉信息融合的技术,…...