初识Linux · 传输层协议TCP · 上
目录
前言:
TCP结构体
首部长度
确认应答机制
捎带应答机制
超时重传机制
连接管理机制
三次握手
SYN_SENT
SYN_RCVD
ESTABLISHED
TCP为什么是三次握手
四次挥手
什么是四次挥手
状态理解
CLOSE_WAIT
LAST_ACK
TIME_WAIT
前言:
前文有关传输层协议,我们介绍了UDP协议的基本字段以及简单介绍了如何UDP添加报头之后,如何分用,如何封装的,并且简单看了一下UDP的基本源码,发现的确很简单。
接着我们引入了报文如何管理起来的问题,我们使用了六字真言,先描述再组织,所以使用结构体sk_buff描述该类型,并且利用了数据结构双链表的方式对其进行管理,我们着重介绍了的是两个指针,分别是head指针和data指针,两个指针的类型都是char*,通过两个指针我们简单展示了报文在向上交付的时候,是如何对UDP的字段赋值的。
那么从本文开始呢,我们介绍TCP协议,TCP协议相对于UDP协议来说要复杂很多,所以我们大概分为两到三篇文章介绍。
本文主要介绍:TCP的字段,确认应答机制,捎带应答机制,连接管理机制。
话不多说,我们直接进入主题吧!
TCP结构体
以上是TCP的协议段格式,我们发现它相对于UDP报头的8字节来说,复杂了不少,比如抛开选项和数据部分,报头部分就有20字节了(还有4位标志位图中没有),而在这里我们能一下就理解的是16位源端口号和16位目的端口号。
那么对于其他字段,我们要介绍的分别是首部长度,6个标志位,16位窗口大小以及32位序号和32位确认序号,其中对于紧急指针我们简单介绍即可,因为实际上应用场景并不是很多。校验和我们暂时先忽略。
在2.62.32版本中的源码中,TCP的源码如下:
struct tcphdr {__be16 source;__be16 dest;__be32 seq;__be32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)__u16 res1:4,doff:4,fin:1,syn:1,rst:1,psh:1,ack:1,urg:1,ece:1,cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)__u16 doff:4,res1:4,cwr:1,ece:1,urg:1,ack:1,psh:1,rst:1,syn:1,fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif __be16 window;__sum16 check;__be16 urg_ptr;
};
可以发现不管是大端还是小端,我们发现一共有10个标志位,其中最为常用的是图中的6个,那么我们依次介绍,从首部长度开始。
首部长度
首部长度在TCP中的作用是用来表示TCP的报头有多长,可以表明数据部分是从多少开始的,因为报头的最小长度是20字节,即不带任何选项。
那么有问题了,我们清晰的看到首部长度的一共只有4位,那么它的表示长度只有[0,15],不管怎么看连TCP最小长度都没有办法表示,所以这里的单位方面做了一点改动,这里的基本单位表示的是4字节,也就是说它实际的范围是[0,60]字节。
通过首部长度字段,接收端能够准确地分离出报文头和数据部分,也就是 定位数据的起始位置,从而可以进行有效的数据解析。
但是要注意,这里的解析数据包并不能有效的解决粘包/拆包等问题,具体我们后面再谈。
那么如果首部长度为5,也就代表了只有一个TCP报头,没有任何选项和数据,在TCP中就显示0101了,如果首部长度为6,表示报头的长度为24字节,此时就包含了额外的选项,比如时间戳一类的。
接下里,我们将结合具体的TCP通信机制来介绍其他字段。
确认应答机制
确认应答机制使用到的字段是标志位ACK以及32位序号和32位确认序号。对于确认应答机制来说,它是TCP保证可靠传输的一个重要机制,在这里我们还需要额外理解一下什么是可靠传输。
假设有两位同学AB,其中AB相隔了100米,他们之间通信只能通过是否听到声音来确定,那么就有以下的通信示意图:
A向B发送消息,B收到了消息,并且给A应答,代表B收到了这条消息,但是很明显,我们能发现一个弊端是AB中间的通信总会有一条消息是没有办法确认是否收到的,即最后一条消息。
现在,我们将AB看作服务器和客户端,A给B发送了报文,如果B对A没有应答,那么A就认为报文丢失,经过特定的时间,A就会触发超时重传机制,重新给B发送报文。
将视角放回到最后一条报文之前,假如之前发送的所有报文都有应答,也就代表C发送的报文S全部收到了,此时这是对确认应答机制最基本的理解。
但是实际上,TCP通信的时候还有另一种发送报文的机制,如图:
即一次性发送多个报文,比如发送了4条报文,分别是1000,2000,3000,4000,S就要应答,应答的报文是1001,2001,3001,4001。
此时可能的问题,或者说确认应答本身有一个问题是,如果应答报文也丢失了呢?
应答报文丢失了,也就代表C收不到应答,也就默认自己发的报文S是没有收到的,既然是没有收到,那么就会重传。
但是实际上,在确认应答机制中规定:连续发送的应答报文中,一个应答报文表示该报文之前的所有报文都收到了。比如C收到了三个应答报文,分别是1001,3001,4001,那么2001没有收到问题不打,因为收到了3001和4001,也就代表了2000的报文是收到了的。
这是确认应答机制中对应答报文丢失做出的处理,对于应答报文来说,它发送之前,会将标志位ACK设置为1,代表这是一个应答报文。
而我们也发现了,所谓的可靠传输,并不是代表所有的报文都能收到,它能保证的可靠传输,是某个报文之前的所有报文都能收到,换句话说,是所有的历史记录都能收到,而非最新的报文一定能收到。
对于上面假设的1000等数字,相信敏锐的同学也发现了,似乎有确认序号有关?那么在介绍下去实在离不开捎带应答了,所以请看下文~
捎带应答机制
对于确认应答机制的第一个图:
B的应答其实并不是完全的应答,应答应该是“吃了”,而不是带上“你呢?”,这其实是一种捎带应答机制,这种机制是将应答报文和数据报文合并为一个报文发送出去的。
这个机制的出现意在提高TCP通信的效率,因为网络通信的时候资源都是宝贵的,在保证通信完整的情况下,能减少通信的次数就减少,如果没有捎带应答机制,那么三次通信就会变成四次通信,一次两次影响不大,但是在如今的网络时代,基本都是常服务,所以影响累计下来是非常大的。
那么捎带应答机制本质还是应答,也会将ACK标志位设置1。
上文提到了序号和确认序号,我们重点来理解什么是序号和确认序号?
首先确认序号=序号+数据长度。
虽然 TCP 的数据发送看似像一个“先进先出”的队列,但其内核实现是由 sk_buff 链表和一组序号变量(如 snd_nxt
, write_seq
, snd_una
)共同维护的高效缓冲结构,支持顺序发送、乱序接收与重传控制。也就是说分配序号是通过这个高效缓冲结构进行维护的,比如A发送1-1000字节的数据,那么序号为1,确认序号为1+1000,1001,即二者都是通过具体的数据长度确定的。
当我们通过sk_buff以及递增变量获取到了序号之后,我们有以下几个应用场景,最主要的是去重,按序到达。
当应答丢失的时候,服务端以为报文丢失,于是触发超时重传,重新传输了一遍报文,此时因为报文携带了对应的序号,在客户端被根据序号进行去重,此时对于客户端来说减少了资源的使用,因为不用额外的资源去管理新来的报文了。
在OS内存在很多的报文,我们知道OS可以通过sk_buff进行报文管理,但是报文如果是杂乱无章的,管理起来还是杂乱无章的,所以利用序号,我们可以有效的按照顺序来对报文进行管理。在这里可能会担心序号超出了32位,实际上不用担心,因为32位本身就很大了,加上内核中是使用的环形缓冲区来维护的,所以基本不会出现序号不够的情况。
那么为什么需要两个序号?而非一个序号?
实际上这个问题,与捎带应答的机制有关,假如携带的报文是为应答报文+数据,那么这个报文要做的工作是给另一个端发送应答,即ACK=1,并且确认上一条报文的序号,此时需要用到确认序号,并且自己因为携带了数据,所以自己也要设置为对应的序号。
这个工作怎么看都不像是一个序号能完成的,即两个序号只能说设置的刚刚好。
在序号里面我们涉及的问题是:序号怎么来的,序号如何计算,序号的作用以及为什么需要两个序号,也是通过捎带应答机制引出来的额外问题。
对于序号的作用如下图,我们在后续文章都会逐渐涉及:
作用领域 | 是否依赖序号 | 描述 |
---|---|---|
数据排序 | ✅ | 重组字节流 |
重传识别 | ✅ | 丢弃重复数据 |
流量控制 | ✅ | 滑动窗口边界依赖序号 |
拥塞控制 | ✅ | 判断是否确认,是否丢包 |
连接同步 | ✅ | 三次握手初始化 |
状态维护 | ✅ | snd_nxt / snd_una / rcv_nxt等核心状态 |
超时重传机制
对于超时重传机制,我们后续结合实际的策略介绍,这里我们记住,服务端发送了报文但是没有收到应答,Linux中设置的是经过了500ms没有收到就会触发超时重传,因为实际上的网络波动是不确定的。
所以一次重传还没收到,那么再过2*500ms,还没有收到就4*500ms,如果仍然收不到按照这种规律累计下去,累积到了一定的次数,就认为两者的连接出现了问题,就强制关闭连接。
实际上的重传还有不止这么简单,比如有快重传,我们后面介绍。
连接管理机制
TCP的连接管理机制,最重要的就是三次握手和四次挥手机制,我们通过以下示意图逐一讲解:
三次握手
介绍握手和挥手之前,我们要清楚OS中存在了很多的报文,其中对于有传输数据的报文,也就是建立连接的报文,也有断开连接到报文,也有应答报文,也有应答加传输数据的报文,根据不同的报文OS内部有自己的一套操作流程体系。
SYN_SENT
那么对于建立连接的报文,内核中的TCP网络协议栈收到请求之后,就会做出相应的处理。
由connect发起建立连接的请求,首先是client先置为SYN_SENT状态,然后构建报文,构建报文的时候发现状态为SYN_SENT,那么就会将报文中的标识符SYN置为1,代表这是一个请求连接的报文。由此,我们能推出一个知识点:先改状态,再发报文。具体是因为构建报文的时候需要根据客户端的状态来正确的构建报文,如果是先构建报文再改状态,那么报文的构建就是不正确的。也就是说,服务端构建 ACK 报文时也必须已处于 SYN_RCVD
状态,以正确设置报文中的标志位。
SYN_RCVD
server收到了SYN报文之后,采用捎带应答的方式,首先状态改变为SYN_RCVD,构建报文的时候将SYN和ACK设置为1,因为建立报文的报文也就是需要应答的,所以这里也需要设置ACK,构建好之后发送给client。
ESTABLISHED
client收到了SYN+ACK的报文之后,状态设置为ESTABLISHED,并且给上述报文应答,ACK设置为1并且发送对应的报文给到server。
以上的这个过程,connect明显参与了对应的连接,而accept真正意义上来讲,是没有参与三次握手的,对于accept来说,它只是通过三次握手,获取到了对应的文件描述符,然后进行后续的一系列操作。
以上是三次握手的一个基本介绍,那么,围绕三次握手,我们同样可以发现一种异常情况,如果最后一个ACK收到,就开始发报文了,该怎么办?
首先最后一个ACK没有收到,那么连接代表是失败的,即发生了异常连接,此时就会未收到ACK的端就会发送一个报文,该报文的RST标志位被设置为1,代表连接重置,即标识这次连接是异常的,需要重新进行连接。
TCP为什么是三次握手
那么关于TCP三次握手能引发的问题有很多,经典问题:为什么TCP是三次握手而不是一次二次?
首先针对这个问题,我们引出另一个概念,即SYN洪水,假如只需要握手一次,那么也就代表了只需要发送一次SYN即可,此时会衍生出一种情况是黑客模拟连接,短时间内发送大量的SYN报文,此时服务器就要一次性处理指数级增长的虚假连接,就容易导致系统崩溃。那么三次握手虽然也会面临SYN洪水,但是相对来说效果要没有那么强烈。
那么以上是一个引申,对于这个问题的核心答案分为两点:
第一点是验证全双工,即网络的连通性。因为TCP是全双工的,三次握手不管怎么看,客户端收发一次报文,服务端收发一次报文,以最少的次数验证了二者能够正常的收发消息。如果是一次握手,无法验证全双工,并且连接状态无法保障,如果是两次握手,无法保证双方都能够正常读写。
第二点是建立双方通信共识的意愿,对于服务端来说,有的连接是需要明确拒绝的,所以有的时候服务器不想进行通信,那么三次握手可以让服务器有效的拒绝连接,并且,网络中会残留旧的建立连接的报文,此时如果服务器恰好收到了,也能有效地通过三次握手判断出是否应该建立连接。
当然了,还有关于TCP三次握手还有很多常见的问题,就留给读者自行探索了~
比如,为什么TCP不是四次五次握手呢?这里我们就简单提及一下,因为连接实际上也是需要维护的,连接的本质是内核数据结构,那么既然是数据结构,维护起来就是需要时间和空间的,所以网络中意在用最少的次数保证最高的效率。
四次挥手
对于四次挥手,涉及到的状态是FIN_WAIT_1/2,以及CLOSE_WAIT和LAST_ACK和TIME_WAIT,我们先重点谈论什么是四次挥手,然后再着重于它涉及的状态讲解。
什么是四次挥手
前文我们介绍了系统中存在很多的报文,报文的类型各不相同,对于四次挥手涉及到的报文是断开连接的请求,所以四次挥手解决的就是断开连接的问题。
那么由图,当客户端关闭了文件描述符,也就是代表我不想和你通信了,此时将状态设置为FIN_WAIT_1,并且发送FIN报文,其中FIN标志位设置为1,标识这是一个断开连接的请求。服务端收到了请求之后,状态设置为CLOSE_WAIT,并且发送应答报文,客户端状态被设置为TIME_WAIT。
当服务端也想断开连接了,状态设置为LAST_ACK,构建FIN报文,给客户端发送FIN报文,此时客户端的状态已经是TIME_WAIT状态,收到FIN报文之后,构建ACK报文并发送,服务端收到之后,状态设置为CLOSED。
敏锐的同学会发现,什么叫做服务端也想断开连接?难道四次挥手不能像三次握手那样进行捎带应答?是的,因为有这么一种情况,客户端是发送完了对应的报文,但是服务端还没有发完,当服务端处理好了对应的报文,此时再断开连接,也就是后两次挥手。
那么既然是有的时候报文没有处理完,直接close文件描述符是不是也不行?直接close掉之后,read都不行了,所以可以使用shutdown接口,按照我们的意愿进行关闭:
此时我们就可以按照需求关闭了。
状态理解
通过上面的图片,我们发现了四次挥手涉及的状态有TIME_WAIT, CLOSE_WAIT,LAST_ACK。
我们现在就来重点理解这三种状态。
CLOSE_WAIT
对于CLOSE_WAIT,这个状态的本质是客户端主动关闭并且发送了FIN报文之后处于的一个中间状态,只要服务端一直不关闭文件描述符,就一直是这个状态,也就是说,服务端如果还有报文没有处理完,那么就会一直处于CLOSE_WAIT状态,并且通过套接字和客户端交互。
那么我们要验证这个状态也很简单,service函数的close我们设置为10秒之后即可:
void Service(int sockfd){while (true){// read writechar buffer[1024];ssize_t n = ::read(sockfd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = 0;std::string echo = "[Server say]# ";echo += buffer;ssize_t wn = ::write(sockfd, echo.c_str(), echo.size());}else if (n == 0){std::cout << "client quit" << std::endl;break;}else{if (errno == EINTR) continue;std::cout << "read error" << std::endl;break;}}sleep(10);::close(sockfd);}
然后我们让一个客户端连接并退出,这个过程我们一直netstat -nltp,就可以看到出现了CLOSE_WAIT并且过了10秒就没了。
如果系统中存在了大量的CLOSE_WAIT,就会导致服务器卡顿,主要原因是因为服务器资源管理不当,导致文件描述符耗尽,无法打开新文件。
LAST_ACK
LAST_ACK
状态的出现时机是服务端在接收到客户端的 FIN
并调用 close()
后进入的状态,表示它正在等待客户端对自己的 FIN
的 ACK。
那么具体操作我们只需要先将客户端断开,再断开服务器,就能查看到对应的状态了,不过一个人不太好测试,可以使用多台机器一起测试:
TIME_WAIT
对于TIME_WAIT状态,我们发现先断开连接的一方会先变成TIME_WAIT状态,那么我们不妨让服务器主动断开,验证它是否会有TIME_WAIT状态。
这是验证结果。
所以其实通过LASK_ACK和TIME_WAIT我们发现服务端和客户端主动断开是不一样的,谁先主动断开就先变成TIME_WAIT状态。
有意思的是,如果我们通过netstat命令查看,我们会发现TIME_WAIT存在的时间是比较久的,大概是60s左右,这个和系统的配置有关。
到这里,我们就需要引出MSL(Maximum Segment Lifetime)报文最大生存时间的概念了,对于TIME_WAIT来说它的存在时间是2*MSL。
为什么是两倍的MSL呢?
我们从两个方面出发:
1. 确保最后的ACK报文能被对方收到,因为四次挥手最后一次的ACK是没有办法确认是否收到的,所以假设ACK没有收到,那么主动关闭连接的一方有足够的时间去重传,并且重传的速度是很快的,所以第一次ACK没收到,等待它消失也就是1个MSL,然后重发,并且再等待一个MSL保证这个ACK消失,避免影响后面的连接。
2. 避免旧连接的报文影响新连接,因为如果我们关闭服务端连接,关闭客户端连接,我们立马重启服务端,我们是发现重启不了的,显示:
就是因为TIME_WAIT还存在,这个时间主要是留给处理旧连接的报文,防止新连接连接到了旧报文导致连接错乱。
那么如果我们想要立即重启,使用的函数为:
int opt = 1;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
以上是传输层协议TCP的部分介绍,更多的介绍移步后文~
感谢阅读!
相关文章:
初识Linux · 传输层协议TCP · 上
目录 前言: TCP结构体 首部长度 确认应答机制 捎带应答机制 超时重传机制 连接管理机制 三次握手 SYN_SENT SYN_RCVD ESTABLISHED TCP为什么是三次握手 四次挥手 什么是四次挥手 状态理解 CLOSE_WAIT LAST_ACK TIME_WAIT 前言: 前文有…...
基于SpringBoot的校园周边美食探索及分享平台的设计与实现
资源详情: 私信我或点击链接获取: 基于SpringBoot的校园周边美食探索及分享平台的设计与实现资源-CSDN文库 摘要 美食一直是与人们日常生活息息相关的产业。传统的电话订餐或者到店消费已经不能适应市场发展的需求。随着网络的迅速崛起,互联…...
系统架构设计-真题2024下半年总结
系统架构设计-真题2024下半年总结 综合知识(选择题)考点分布选择题详细解释ABSD方法简介 选项分析生活化例子概念讲解系统的质量目标系统的商业目标系统开发人员的商业目标 简单记法总结基于内容推荐的优点选项分析正确答案总结 综合知识(选择…...
《React Native性能优化:从卡顿到丝滑的蜕变之旅》
《React Native性能优化:从卡顿到丝滑的蜕变之旅》 前言:当你的React Native应用开始"便秘"… “这破应用怎么又卡了?!”——如果你也曾在测试自己的React Native应用时发出这样的呐喊,那么你不是一个人在怒吼。想象一下这样的场景:你精心打造的APP在低端安卓…...
flutter build apk出现的一些奇怪的编译错误
我换了新电脑后重新编译基于livekit 的 flutter livekit工程,然后编译的时候一直报flutter_webrtc的 0.11.7 版本的dart代码有一个接口未实现,我比较了所以环境和版本实现找不到问题,根本不正常哪里导致的问题 ,以前的电脑的环境一…...
枚举 · 例8扩展-校门外的树:hard
登录—专业IT笔试面试备考平台_牛客网 代码区: #include<algorithm> #include<iostream> #include<vector>using namespace std; struct TREE{int left,right; }; bool compare(const TREE&a,const TREE& b ){if(a.left!b.left){return…...
监控系统进阶方案:OpenObserve的Docker部署与远程访问配置指南
文章目录 前言1. 安装Docker2. 创建并启动OpenObserve容器3. 本地访问测试4. 公网访问本地部署的OpenObserve4.1 内网穿透工具安装4.2 创建公网地址 5. 配置固定公网地址 前言 今天,我想分享一个在云原生可观测性领域备受关注的开源项目——OpenObserve。在复杂的云…...
如何通过grep 排除“INTEGER: 1”
在 Linux/Unix 系统中,使用 grep 过滤数据并 取反(排除匹配内容) 的核心选项是 -v(反向匹配)。以下是具体用法和场景示例: 1. 基础用法:排除包含指定关键词的行 # 语法 grep -v "pattern&…...
基于Qt开发的http/https客户端
成果展示: 使用Qt开发HTTP客户端主要依赖QNetworkAccessManager、QNetworkRequest和QNetworkReply三大核心类。以下是具体实现要点及最佳实践: 一、核心类与基础流程 1.QNetworkAccessManager 作为HTTP请求的管理者,负责异步处理…...
微程序控制器的详细工作过程
1. 基本组成结构 微程序控制器主要由以下部件构成: 控制存储器(Control Store, CS):存储微程序(微指令集合),通常使用ROM或EPROM。 微地址寄存器(μAR):存放…...
PostgreSQL 的 pg_current_logfile 函数
PostgreSQL 的 pg_current_logfile 函数 pg_current_logfile() 是 PostgreSQL 9.6 版本引入的一个系统管理函数,用于获取当前正在使用的日志文件路径。 一 基本用法 1 函数定义 pg_current_logfile([text]) → text2 简单查询 -- 获取当前日志文件路径 SELECT …...
实时云渲染——比像素流送节省80%精力的UE程序推流技术
UE5引擎除了适合开发3A游戏,同样适用于开发大场景高精度的数字孪生可视化场景,自带的Nanite 虚拟微多边形几何体技术、Lumen 全动态全局光照技术、高度可扩展的架构、强大的地形和植被系统以及高效的流媒体技术,使UE5在数字孪生领域的技术占有…...
如何解决 Linux 系统文件描述符耗尽的问题
在Linux系统中,文件描述符(File Descriptor, FD)是操作系统管理打开文件、套接字、管道等资源的抽象标识。当进程或系统耗尽文件描述符时,会导致服务崩溃、连接失败等严重问题。以下是详细的排查和解决方案: --- ###…...
存储器:DDR和HBM的区别
本文简要介绍DDR(Double Data Rate SDRAM)和HBM(High Bandwidth Memory)的主要区别: 1. 架构与设计 DDR:传统的主流动态随机存取存储器(DRAM),采用并行总线架构&#x…...
【计算机网络】Cookie、Session、Token之间有什么区别?
大家在日常使用浏览器时可能会遇到:是否清理Cookie?这个问题。 那么什么是Cookie呢?与此相关的还有Session、Token这些。这两个又是什么呢? 本文将对这三个进行讲解区分,如果对小伙伴有帮助的话,也请点赞、…...
每日学习:DAY24
日常开发与学习记录 前言 怎么感觉自己越来越懒了。 日程 忘记写了,大概是早上做了 SQL 表单,晚上写了 DispatcherController。 学习记录 操作系统 页面分配置换策略 学习内容 省流 SQL 表单构建关于嵌套注解的生效机制DispatcherController 统…...
grpo原理
图解deepseek的grpo原理、以debug形式阅读grpo的源码 练习两天半,从零实现DeepSeek-R1(基于Qwen2.5-0.5B和规则奖励模型,GRPO),从原理讲解到代码实现,解开DeepSeek-R1的神秘面纱 第一个视频 GRPO讲解 mod…...
RabbitMQ--基础篇
RabbitMQ 简介:RabbitMQ 是一种开源的消息队列中间件,你可以把它想象成一个高效的“邮局”。它专门负责在不同应用程序之间传递消息,让系统各部分能松耦合地协作 优势: 异步处理:比如用户注册后,主程序将发…...
ResNet残差神经网络的模型结构定义(pytorch实现)
ResNet残差神经网络的模型结构定义(pytorch实现) ResNet‑34 ResNet‑34的实现思路。核心在于: 定义残差块(BasicBlock)用 _make_layer 方法堆叠多个残差块按照 ResNet‑34 的通道和层数配置来搭建网络 import torch…...
如何使用极狐GitLab 软件包仓库功能托管 ruby?
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 软件包库中的 Ruby gems (BASIC ALL) WARNING:Ruby gems 软件包库正在开发中,由于功能有限,尚未准备好…...
AI日报 · 2025年5月08日|Stripe发布全球首个支付AI基础模型
1、Stripe 发布支付领域专用 AI 基础模型及稳定币账户功能 Stripe 于5月7日在其年度 Sessions 大会上发布了全球首个专为支付领域打造的 AI 基础模型——“Payments Foundation Model”,该模型基于数百亿笔交易数据训练,能够捕捉每个支付中数百个传统模…...
React 笔记[1] hello world
React 笔记[1] hello world 明白了!既然你已经安装了 Node.js,我们可以 从零开始搭建一个 React Tailwind CSS 的 Hello World 项目。我将一步步列出操作指令,你只需要在终端里依次执行。 ✅ 第一步:初始化项目 mkdir my-hello…...
好消息!PyCharm 社区版现已支持直接选择 WSL 终端为默认终端
在过去,PyCharm 社区版虽然提供了链接 Windows 子系统 Linux(WSL)终端的能力,但用户无法在设置中直接指定 WSL 为默认终端,这一功能仅限于专业版使用者。 而现在,在 PyCharm 2025.1.1 版本中,Je…...
基于redis的定时状态更新
基于redis的定时状态更新 下面是一个简单的示例,展示如何使用redis实现状态更新,从而满足在某些场景下,既需要频繁更新状态, 又需要保证状态的实时性。以及定时更新状态的需求。 示例说明 假设有一个剧目演出计划,确…...
[原创](现代Delphi 12指南):[macOS 64bit App开发]: 如何获取自身程序的所在的目录?
[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...
服务器托管的常见问题
一、何谓IDC服务器托管服务? IDC服务器托管是指为了提高网站的访问速度,将您的服务器及相关设备托管到具有完善机房设施、高品质网络环境、丰富带宽资源和运营经验以及可对用户的网络和设备进行实时监控的网络数据中心内,以此使系统达到安全、可靠、稳定…...
使用Scrapeless Scraping Browser的自动化和网页抓取最佳实践
引言:人工智能时代浏览器自动化和数据收集的新范式 随着生成性人工智能、人工智能代理和数据密集型应用程序的快速崛起,浏览器正在从传统的“用户互动工具”演变为智能系统的“数据执行引擎”。在这一新范式中,许多任务不再依赖单一的API端点…...
电子电气架构 --- 如何有助于提安全性并减少事故
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...
【训练】Qwen2.5VL 多机多卡 Grounding Box定位
之前的相关文章: 【深度学习】LLaMA-Factory微调sft Qwen2-VL进行印章识别 https://www.dong-blog.fun/post/1661 使用LLaMA-Factory微调sft Qwen2-VL-7B-Instruct https://www.dong-blog.fun/post/1762 构建最新的LLaMA-Factory镜像 https://www.dong-blog.f…...
MYSQL的行级锁到底锁的是什么东西
MySQL 的行级锁是一种锁机制,它允许数据库在执行并发操作时,锁定表中的某一行数据而不是整张表。行级锁通过限制对特定行的访问,允许其他线程并发地访问表中的其他行,从而提高并发性和性能。 行级锁的锁定对象 行级锁锁定的是 行…...
图神经网络中的虚拟节点
1.虚拟节点 当我们使用节点来构成图结构时, regular node: 常规的节点即代表了某一个局部特征, 即局部节点特征。 virtual node: 普通的节点不同,有时会需要这样的一种特征, 该特征代表了该样本的全局信息࿰…...
关于多版本CUDA共存的研究,是否能一台机子装两个CUDA 版本并正常切换使用
我发现了一个很有意思的事 我装了11.8cuda再装12.3cuda结果我的11.8cuda还在,没被替换掉或者删掉 然后我打开我的环境发现它的环境除了cuda_path都没改 这样我就有个大胆的想法,如果我把cuda path换成11.8路径那是不是就能切换了 而且cuda_path 和 cuda_…...
el-table与echarts图形实现滚动联动
el-table与echarts图形滚动联动 效果图 实现思路 设计图滚动条位于表格下方,且echarts滚动不易获取当前展示数据到左侧的距离 故:通过监听表格的滚动实现联动 为了保持echarts的横坐标和表格的列基本保持对齐,用tdWidth标识单列表格的宽度…...
【Git】【commit】查看未推送的提交查看指定commit的修改内容合并不连续的commit
文章目录 1. 查看未推送的提交方法一 :git status方法二:git log方法三:git cherry方法四:git rev-list 2. 查看指定commit的修改方法一:git show方法二:git log方法三:git diff 3. 合并不连续的…...
C++GO语言微服务基础技术①
目录 01-项目简介 02-单体式架构 03-微服务优缺点 04-单体式和微服务区别 05-RPC简介 06-RPC使用步骤 07-注册RPC服务函数接口 08-绑定服务和调用方法函数接口 09-rpc服务端和客户端编码实现 10-json的rpc 11-rpc的封装 12-rpc封装小结 01-项目简介 # 单体式和微服…...
AI CUBE 使用指南 目标检测格式范例 AI cube 报错数据集不合规范,请清洗数据集
血的教训:labels.txt里面放1 2 3 4 ..也可以英文,不能有中文 教程:K230 借助 AICube部署AI 视觉模型 YOLO等教程_嘉楠 ai cube多标签分类-CSDN博客 | 目标检测范例: 不清楚不是数字行不行 这个id可以英文,你…...
vue中scss使用js的变量
一、前言 在项目开发中,很多时候会涉及到scss样式变量,正常定义方式 $primary-color: rgb(188, 0, 194);;使用时直接使用即可:color: $primary-color。但是,如果,这些变量是在js中定义的怎么办 二、实现 …...
QtGUI模块功能详细说明, 字体和文本渲染(四)
目录 一. 窗口和屏幕管理 二. 绘图和渲染 三. 图像处理 四. 字体和文本 1、核心概念 1.1、字体 (Font) 1.2、字形 (Glyph) 1.3、字符 (Character) 1.4、文本布局 (Text Layout) 1.5、文本渲染 (Text Rendering) 1.6、度量 (Metrics) 2、字体管理 2.1、QFont&#…...
计算机学习路线与编程语言选择(信息差)
——授人以鱼不如授人以渔 面向岗位学习!到招聘网站看看有哪些岗位,看一看岗位职责、要求 牛客网(计算机实习工作最好的网站) boss直聘 确定岗位后(如前端、后端),岗位需要什么语言…...
多环串级PID
文章目录 为什么要多环程序主函数内环外环 双环PID调参内环Kp调法Ki调法 外环Kp 以一定速度到达指定位置封装 为什么要多环 单环只能单一控制速度或者位置,如果想要同时控制多个量如速度,位置,角度,就需要多个PID 速度环一般PI…...
编写大模型Prompt提示词方法
明确目标和任务 // 调用LLM进行分析const prompt 你是一名严格而友好的英语口语评分官,专业背景包括语音学(phonetics)、二语习得(SLA)和自动语音识别(ASR)。你的任务是: ① 比对参…...
使用chrome浏览器截长图
如何使用chrome浏览器截长图: 使用chrome截取完整网页图片 第一步、按F12,开发者模式的布局按下图布局 第二步、按ctrlshiftp组合键,搜索“截图” ,然后自动截图保存在下载目录(右上角)了。...
【MySQL】第二弹——MySQL表的增删改查(CURD))
文章目录 🎓一. CRUD🎓二. 新增(Create)🎓三. 查询(Rertieve)📖1. 全列查询📖2. 指定列查询📖3. 查询带有表达式📖4. 起别名查询(as )📖 5. 去重查询(distinct)📖6. 排序…...
Android NDK版本迭代与FFmpeg交叉编译完全指南
在Android开发中,使用NDK(Native Development Kit)进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时。本文将深入分析Android NDK的版本迭代分界线,详细讲解FFmpeg交叉编译的注意事项,并提供完整的…...
【Linux网络】Socket-UDP相关函数
socket() 函数 这个函数的作用是创建一个 Socket 文件描述符,在客户端和服务器都可以使用。 #include <sys/socket.h> int socket(int domain, int type, int protocol);参数: domain:指定协议族,例如 AF_INET 代表 IPv4 …...
最优化方法Python计算:有约束优化应用——线性Lasso回归预测器
实际应用中,特征维度 n n n通常远大于样本容量 m m m( n ≪ m n\ll m n≪m),这种高维小样本场景下特征数据可能含有对标签数据 y i y_i yi的取值不必要的成分,甚至是噪声。此时,我们希望回归模型中的优化…...
基础算法 —— 二分算法 【复习总结】
1. 简介 1.1 原理 二分算法,顾名思义,关键在于二分,当我们求解的目标具有二段性时,我们就可以使用二分算法: 先根据待查找区间中点位置,判断结果会在左侧还是右侧,接下来,舍弃一半…...
计算机网络常识:缓存、长短连接 网络初探、URL、客户端与服务端、域名操作 tcp 三次握手 四次挥手
缓存: 缓存是对cpu,内存的一个节约:节约的是网络带宽资源 节约服务器的性能 资源的每次下载和请求都会造成服务器的一个压力 减少网络对资源拉取的延迟 这个就是浏览器缓存的一个好处 表示这个html页面的返回是不要缓存的 忽略缓存 需要每次…...
OpenHarmony平台驱动开发(九),MIPI DSI
OpenHarmony平台驱动开发(九) MIPI DSI 概述 功能简介 DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface (MIPI) Alliance)制定的规范,旨在降…...
经济体制1
一.计划经济体制与市场经济体制 1.计划经济又称指令型经济,是对生产和资源分配以及产品消费事先进行计划的经济体制。 市场经济体制是指依靠市场手段对资源进行配置的经济体制 注意: 计划与市场都是调节经济的手段,都属于资源配…...