当前位置: 首页 > news >正文

【Linux网络#17】TCP全连接队列与tcpdump抓包

一、TCP 相关实验 测试

1. Listen 的第二个参数

LISTEN(2)                                    Linux Programmer's Manual                                                          
NAMElisten - listen for connections on a socketSYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int listen(int sockfd, int backlog);
  • 基于封装的 TcpSocket 实现以下测试代码
  • 对于服务器, listen 的第二个参数设置为 1, 并且不调用 accept
  • 测试代码如下:

Makefile

.PHONY:all
all:tcp_server tcp_clienttcp_server:TcpServer.ccg++ -o $@ $^ -std=c++14
tcp_client:TcpClient.ccg++ -o $@ $^ -std=c++14.PHONY:clean
clean:rm -rf tcp_server tcp_client

TcpClient.cc

#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>int main(int argc, char **argv)
{if (argc != 3){std::cerr << "\nUsage: " << argv[0] << " serverip serverport\n"<< std::endl;return 1;}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (clientSocket < 0){std::cerr << "socket failed" << std::endl;return 1;}sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(serverport);                  // 替换为服务器端口serverAddr.sin_addr.s_addr = inet_addr(serverip.c_str()); // 替换为服务器IP地址int result = connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));if (result < 0){std::cerr << "connect failed" << std::endl;::close(clientSocket);return 1;}while (true){std::string message;// std::cout << "Please Enter@ ";std::getline(std::cin, message);if (message.empty())continue;send(clientSocket, message.c_str(), message.size(), 0);char buffer[1024] = {0};int bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);if (bytesReceived > 0){buffer[bytesReceived] = '\0'; // 确保字符串以 null 结尾std::cout << "Received from server: " << buffer << std::endl;}else{std::cerr << "recv failed" << std::endl;}}::close(clientSocket);return 0;
}

TcpServer.cc

#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>const static int default_backlog = 1;enum
{Usage_Err = 1,Socket_Err,Bind_Err,Listen_Err
};#define CONV(addr_ptr) ((struct sockaddr *)addr_ptr)class TcpServer
{
public:TcpServer(uint16_t port) : _port(port), _isrunning(false){}// 都是固定套路void Init(){// 1. 创建socket, file fd, 本质是文件_listensock = socket(AF_INET, SOCK_STREAM, 0);if (_listensock < 0){exit(0);}int opt = 1;setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));// 2. 填充本地网络信息并bindstruct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = htonl(INADDR_ANY);// 2.1 bindif (bind(_listensock, CONV(&local), sizeof(local)) != 0){exit(Bind_Err);}// 3. 设置socket为监听状态,tcp特有的if (listen(_listensock, default_backlog) != 0){exit(Listen_Err);}}void ProcessConnection(int sockfd, struct sockaddr_in &peer){uint16_t clientport = ntohs(peer.sin_port);std::string clientip = inet_ntoa(peer.sin_addr);std::string prefix = clientip + ":" + std::to_string(clientport);std::cout << "get a new connection, info is : " << prefix << std::endl;while (true){char inbuffer[1024];ssize_t s = ::read(sockfd, inbuffer, sizeof(inbuffer)-1);if(s > 0){inbuffer[s] = 0;std::cout << prefix << "# " << inbuffer << std::endl;std::string echo = inbuffer;echo += "[tcp server echo message]";write(sockfd, echo.c_str(), echo.size());}else{std::cout << prefix << " client quit" << std::endl;break;}}}void Start(){_isrunning = true;while (_isrunning){sleep(1);// 4. 获取连接struct sockaddr_in peer;socklen_t len = sizeof(peer);int sockfd = accept(_listensock, CONV(&peer), &len);if (sockfd < 0){continue;}ProcessConnection(sockfd, peer);}}~TcpServer(){}private:uint16_t _port;int _listensock; // TODObool _isrunning;
};using namespace std;void Usage(std::string proc)
{std::cout << "Usage : \n\t" << proc << " local_port\n"<< std::endl;
}
// ./tcp_server 8888
int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);return Usage_Err;}uint16_t port = stoi(argv[1]);std::unique_ptr<TcpServer> tsvr = make_unique<TcpServer>(port);tsvr->Init();tsvr->Start();return 0;
}

【案例】:对测试代码进行修改,如下:

🌿将 backlog 的值修改为 1,并且注释掉 accept 代码

image-20250228171339029

此时启动 1 个客户端同时连接服务器, 用 netstat 查看服务器状态, 一切正常,如下:

image-20250228171458049

此时可以看到两条链接,由于 TCP 是全双工的,因此当我们客户端和服务端在同一台主机上,建立连接启动之后,netstat 就能查到两个,服务端 到 客户端,客户端 到 服务端

从这个例子我们可以知道,即使我们的上层不调用 accept , 客户端依然可以连接

  • 因此我们可以知道 三次握手 建立连接的过程与三次握手无关,其会在底层自动把链接建立好
  • 那么 accept 的本质其实就是把一个建立好的连接 通过 accept 以文件描述符 fd 的方式给用户返回,拿上来就行了

然后启动 2 个客户端同时连接服务器, 用 netstat 查看服务器状态, 仍然一切正常,但是启动第 3 个客户端时, 发现服务器对于第 3 个连接的状态存在问题了,如下:

image-20250228172903291

我们可以看到 正常连接的前两台主机,都有两个连接(客户端 <==> 服务端),而且状态均是 ESTABLISHED,而第三台服务端出现了 SYN_SENT,并且连接也只有一个,说明连接建立失败

2. 出现 SYN_SENT 原因

之前已经讲过了三次握手的基本流程,如下:

  • 第一次握手 :客户端发送 SYN 标志,表示发起连接请求;
  • 第二次握手 :服务器收到请求后,发送 SYN+ACK ,表示接受请求并同步;
  • 第三次握手 :客户端确认连接,发送 ACK

三次握手完成后,连接进入全连接队列,但此时应用层可能尚未处理这个连接请求

image-20250228173614448

💻 那么为什么上面客户端状态正常,但是服务器端出现了 SYN_RECV 状态,而不是 ESTABLISHED 状态

原因:Linux 内核协议栈为一个 tcp 连接管理使用两个队列:

  • 半连接队列(syn queue): 存储已发送 SYN 的连接,但尚未完成三次握手的连接。每当收到 SYN 请求,服务器将这个连接放入半连接队列,直到三次握手完成或超时失败。(用来保存处于 SYN_SENTSYN_RECV 状态的请求)
  • 全连接队列(accpetd 队列): 三次握手完成后,连接进入全连接队列,等待被应用层(通常是通过 accept() 函数)处理。如果全连接队列已满,新连接将被丢弃。 (用来保存处于 ESTABLISHED 状态, 但是应用层没有调用 accept 取走的请求)
    • 🔗 而全连接队列的长度会受到 listen 第二个参数(backlog)的影响,全连接队列满了的时候,就无法继续让当前连接的状态进入 ESTABLISHED 状态了.

这个队列的长度通过上述实验可知,是 listen 的第二个参数(backlog) + 1

结论:

listen 的第二个参数的本质是当服务器压力很大或者来不及获取(accept)新连接的时候,操作系统就会在底层(tcp 层)为我们维护一个全连接队列,这个队列会把新到来的连接维护起来,当我们未来需要的时候再把新连接获取上去,这个队列的最大长度叫做 backlog + 1

3. 理解全连接队列

💻 在操作系统中的传输层中有一个接收队列 accept_queue,建立连接时需要进行三次握手。操作系统中用户访问的网站多种多样,并且会并发的运行,所以在操作系统内部一定是要通过数据结构来进行管理的!

  • 连接本质就是操作系统内核中的一批数据结构!

 在传输层中将这个数据结构放入队列中进行管理!应用层会调用 accept 获取连接,传输层就会返回给一个 文件描述符fd 供应用层使用,通过这个文件描述符,应用层就可以进行通信!这个队列就是 全连接队列

🦈 当应用层非常忙,来不及 accept 的时候,那么此时 全连接队列 就会挤压连接,这个总数不能超过 backlog !这个并不代表服务端只能同时处理 backlog + 1 个连接。全连接队列中的连接表示连接成功,但是来不及及时处理的连接!

全连接队列的本质就是一组 生产消费者模型,应用层从其中获取资源,传输层向其中放入资源!

  • 这个队列保证了在应用层较忙时无法获取连接时,可以先将一些连接维护起来,等待应用层调用。
  • 这样可以大大提升效率,提高连接吞吐量!减少服务端闲置率,增加给用户提供服务的效率和体验!这也是为什么全连接队列不能为空,也不能太长的原因

看了上面,我们再从 内核 的角度 来理解 全连接队列

🍺 当服务器启动时,本质上是启动一个进程,那么就会有对应的 task_struct。在这个结构体中都会有 struct files_struct!其中包含文件描述符表 struct file*fd_array[] ,每个元素都指向文件结构体 struct file

当创建网络套接字时,会创建一个 struct socket 结构体!在内核中时这样一个结构:

struct socket {socket_state 			tate;unsigned long			flags;const struct proto_ops 	*ops; struct fasync_struct	*fasync list;struct_file				*file;struct sock				*sk;wait_queue_head_t    	wait;short					type;
};

此时可以看到 struct socket 结构体内部有一个 struct file 结构体,但是未来我们是想通过文件描述符找到对应的套接字,然后进行读取数据。可是现在是 struct socket 结构体内部有一个 struct file 结构体,如果通过 struct file 结构体找到套接字呢?

🐑 在 struct file 结构体有一个指针 void* private_data, 这个指针指向 struct socket 结构体。这样两个结构体就联系起来了!

image-20250228200749811

📐 struct socket 结构体是 网络 Socket 的入口,其内部还包含一个 const struct proto_ops 结构体

image-20250228200829566

  • 这是一个方法集,集合了 bind,connect… 一系列的函数指针!

虽然我们 struct socket 结构体是内核中的套接字结构,但建立连接时真实的数据结构是 struct socket 结构体中 struct sock *sk 所指向的 tcp_sock 结构体!

image-20250228201452831

🛜 这是 TCP 套接字,其中包含了慢启动算法阈值,拥塞窗口大小,关联进程… 一系列 TCP 协议中的对应字段!这个 tcp_sock 就是三次握手时候建立的结构体!其中的第一个成员 struct inet_connection_sock 是复制连接属性的! 这里就包含连接的相关信息。全连接队列就在这个结构体中!

结构体如下:

struct inet connection sock{/* inet sock has to be the first member! */struct inet_sock 			icsk_inet;struct request_sock_queue 	icsk_accept_queue;struct inet_bind_bucket		*icsk_bind_hash;unsigned long				icsk_timeout;struct timer_list			icsk_retransmit_timer;struct timer_list			icsk_delack_timer;__u32						icsk_rto;__u32						icsk_pmtu_cookie;const struct tcp_congestion_ops *icsk_ca_ops;const struct inet_connection_sock_af_ops *icsk_af_ops;unsigned int		 		(*icsk sync mss)(struct sock *sk, u32 pmtu);__u8						icsk_ca_state;__u8						icsk_retransmits;__u8						icsk_pending;__u8						icsk_backoff;__u8						icsk_syn_retries;__u8						icsk_probes_out;__u16						icsk_ext_hdr_len;struct{__u8					pending;  	/* ACK is pending*/__u8					quick;		/*Scheduled number of quick acks*/__u8					pingpong; 	/* The session is interactive*/__u8					blocked;  	/* Delayed ACK was blocked by socket lock */__u32					ato;		/* Predicted tick of soft clock*/unsigned 				longtimeout;/* Currently scheduled timeout*/__u32					lrcvtime;	/* timestamp of last received data packet */__u16					last_seg_size;/* Size of last incoming segment*/ __u16					rcv_mss;	/* MSS used for delayed Ack decisions*/}icsk_ack;...
}

这里有超时重传的触发时间,TCP 连接的状态,握手失败重试次数,全连接队列…等数据。

request_accept_queue(全连接队列)结构体如下:

struct request_sock_queue {struct request_sock 	*rskq accept head;struct request_sock 	*rskg accept tail;rwlock_t				syn_wait_lock;u8						rskq_defer_accept;/* 3 bytes hole, try to pack */struct listen_sock		*listen opt;  
};

struct inet_connection_sock 中的第一个成员是 struct inet_sock 结构体,这是网络层的结构体。

image-20250228203154268

🏡 struct inet_sock 结构体其中包含了 目的端口号,源端口号,目的 IP 地址 和 源 IP 地址 等数据!更重要的是其中第一个成员是 struct sock 结构体,里面包含着报文的一些属性 。

  • 这是整个 tcp_sock 中最底层的结构体,其中有两个字段:接收队列发送队列

image-20250228203307563

struct sk_buff_head sk_receive_queue;
struct sk_buff_head sk_write_queue;
  • 这两个队列对于网络通信至关重要,因为它们直接参与了数据的接收和发送过程

然后我们再来看看 sock 结构体,如下:

image-20250228203449684

我们再回过来看 struct socket,其中有一个结构体指针 struct sock* sk,这个指针可以指向 tcp_sock 中最底层的 struct sock 结构体,然后可以通过类型转换,最终读取到整个 tcp_sock 结构体!也就是说,这个指针指向了 tcp_sock 结构体!

  • 通过强制类型转换 这个指针可以直接指向 struct sockstruct inet_sock struct ine_connection_sock 访问对应的数据

image-20250228203732785

通过结构体嵌套的方式,使用公共指针指向结构体头部对象的方式 这就是 C风格的多态! 此时 struct sock 就是基类!

struct socket{socket_state 			state;unsigned long 			flags;const struct proto_ops 	*ops;struct fasync_struct	*fasync_list;struct file				*file;struct sock				*sk;wait_queue_head_t		wait;short					type;
}
  • 同样的创建 UDP 套接字时,udp_sock 的第一个成员是 struct inet_sock 结构体(因为 udp 不需要连接所以没有包含连接属性结构体)。那么最终也是一个 struct sock 结构体,所以也可以通过C风格的多态实现!

通过 基类 struct socket,我们可以进行 tcp 和 udp 的通信,所以说他是网络 socket 的入口。
image-20250228204210520

二、全连接队列满

如果全连接队列已满,新的完成握手的连接会被丢弃,客户端可能收到ECONNREFUSED错误或超时

原因如下:

  1. 应用处理速度不足
    • 应用程序调用accept()的速度跟不上新连接的到达速度
  2. 队列长度设置过小
    • 操作系统默认的全连接队列长度(如Linux的net.core.somaxconn)不足以应对高并发
  3. 突发流量冲击
    • 瞬时大量连接请求导致队列快速填满
  4. 资源限制
    • 文件描述符(FD)耗尽或内存不足,无法接收新连接

采取的优化措施如下:

① 调整队列长度,适用于 默认配置不足时

  • 修改内核参数(以Linux为例):

    # 查看当前全连接队列最大值
    sysctl net.core.somaxconn# 临时修改(重启失效)
    sysctl -w net.core.somaxconn=1024# 永久修改(写入配置文件)
    echo "net.core.somaxconn=1024" >> /etc/sysctl.conf
    sysctl -p
    
  • 应用程序设置:确保listen(fd, backlog)中的backlog参数与somaxconn一致。

listen(sockfd, 1024);

② 提升应用处理能力,适用于高并发且应用处理慢

  • 多线程/进程模型:为每个连接分配独立线程/进程处理。
  • 异步I/O(如epoll/kqueue):使用事件驱动模型(如Nginx、Node.js)高效处理并发。
  • 连接批处理:单次accept()调用接收多个连接,减少系统调用开销。

③ 负载均衡与横向扩展,适用于单机资源瓶颈

  • 多服务器分发:通过负载均衡器(如Nginx、HAProxy)将请求分散到多台服务器。
  • 自动扩缩容:云环境下根据流量自动增加服务器实例(如Kubernetes HPA)。

④ 监控与告警,适用于预防性维护

  • 监控队列状态

    # 查看全连接队列溢出情况(Linux)
    netstat -s | grep "times the listen queue of a socket overflowed"
    ss -lnt | grep "Recv-Q"
    
  • 告警阈值:当溢出次数持续增长时触发告警,及时扩容或优化。

⑤ 优雅降级与限流

  • 队列满时拒绝新连接:返回503 Service Unavailable或自定义错误页面。
  • 限流措施:使用令牌桶或漏桶算法限制新连接速率(如iptables限速)。

⑥ 资源优化,适用于资源不足导致队列溢出

  • 增加文件描述符限制

    # 修改系统级和进程级FD限制
    echo "fs.file-max=100000" >> /etc/sysctl.conf
    ulimit -n 65535
    
  • 内存与TCP参数调优

    # 调整TCP缓冲区大小
    sysctl -w net.ipv4.tcp_mem="9437184 12582912 16777216"
    sysctl -w net.ipv4.tcp_rmem="4096 87380 6291456"
    sysctl -w net.ipv4.tcp_wmem="4096 16384 4194304"
    

三、TCP dump 抓包

TCPDump 是一款强大的网络分析工具,主要用于捕获和分析网络上传输的数据包。

  • 这里我们使用其 进行抓包,分析 TCP 过程

1. 安装 tcpdump

🎁 tcpdump 通常已经预装在大多数 Linux 发行版中。 如果没有安装, 可以使用包管理器进行安装。

例如 Ubuntu, 可以使用以下命令安装:

sudo apt-get update
sudo apt-get install tcpdump
  • 而在 Red Hat 或 CentOS 系统中, 可以使用以下命令:
sudo yum install tcpdump

2. 常见使用

① 捕获所有网络接口上的 TCP 报文

① 使用以下命令可以捕获所有网络接口上传输的 TCP 报文:

$ sudo tcpdump -i any tcp

注意: -i any 指定捕获所有网络接口上的数据包, tcp 指定捕获 TCP 协议的数据包。 i 可以理解成为 interface 的意思

② 捕获指定网络接口上的 TCP 报文

  • 如果你只想捕获某个特定网络接口(如 eth0) 上的 TCP 报文, 可以使用以下命令:
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.18.45.153 netmask 255.255.192.0 broadcast
172.18.63.255inet6 fe80::216:3eff:fe03:959b prefixlen 64 scopeid
0x20<link>ether 00:16:3e:03:95:9b txqueuelen 1000 (Ethernet)RX packets 34367847 bytes 9360264363 (9.3 GB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 34274797 bytes 6954263329 (6.9 GB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0$ sudo tcpdump -i eth0 tcp

③ 捕获特定源或目的 IP 地址的 TCP 报文

  • 使用 host 关键字可以指定 源或目的 IP 地址。 例如, 要捕获源 IP 地址为 192.168.1.100 的 TCP 报文, 可以使用以下命令:
$ sudo tcpdump src host 192.168.1.100 and tcp

【案例】

image-20250228211937461

  • 要捕获目的 IP 地址为 192.168.1.200 的 TCP 报文, 可以使用以下命令:
$ sudo tcpdump dst host 192.168.1.200 and tcp
  • 同时指定源和目的 IP 地址, 可以使用 and 关键字连接两个条件:
$ sudo tcpdump src host 192.168.1.100 and dst host 192.168.1.200 and tcp

捕获特定端口的 TCP 报文

  • 使用 port 关键字可以指定端口号。 例如, 要捕获端口号为 80 的 TCP 报文(通常是HTTP 请求) , 可以使用以下命令:
$ sudo tcpdump port 80 and tcp

保存捕获的数据包到文件

  • 使用 -w 选项可以将捕获的数据包保存到文件中, 以便后续分析。 例如:
$ sudo tcpdump -i eth0 port 80 -w data.pcap

这将把捕获到的 HTTP 流量保存到名为 data.pcap 的文件中。

  • 了解: pcap 后缀的文件通常与 PCAP(Packet Capture) 文件格式相关, 这是一种用于捕获网络数据包的文件格式

从文件中读取数据包进行分析

🍑 使用 -r 选项可以从文件中读取数据包进行分析。 例如:

tcpdump -r data.pcap

这将读取 data.pcap 文件中的数据包并进行分析

注意事项

  • 使用 tcpdump 时, 请确保你有足够的权限来捕获网络接口上的数据包。 通常, 你需要以 root 用户身份运行 tcpdump
  • 使用 tcpdump 的时候, 有些主机名会被云服务器解释成为随机的主机名, 如果不想要, 就用 -n 选项
    主机观察三次握手的第三次握手, 不占序号

当我们带上 -n 时,会如下:

image-20250228212101556

在上面我们也可以看到,此时我们抓到了 Flags 为 S 的 SYN 报文

3. 抓包验证三次握手和四次挥手的过程

此时需要用到上面的测试代码进行验证:

  • 将服务端和客户端同时启动, 可以看到下面三个就是 SYNSYN + ACKACK , 可以看到第二个 ACK 就是对第一个 SYN 的确认序号

image-20250228213340090

第三次的 ACK 就自动置 1 了, 双方开始正常通信

image-20250228214043501

此时我们直接 CTRL + C 杀掉客户端 可以发现抓取到 FIN 标识位 和 ACK 但是为什么只有两次挥手呢?

image-20250228214219473

  • 此时我们有理由相信我们代码中是有 bug 的!! 很有可能没有关闭文件描述符!!!

查看代码,发现我们雀氏没有关闭 fd ,如下:

image-20250228214524607

但是由于客户端和服务器关闭连接几乎是同时的,此时就造成了捎带应答!!!,如下:

image-20250228215112432

而如果我们是让服务器 sleep 1 秒再退出,结果会咋样呢?

image-20250228215347682

结果如下:

image-20250228215324562

  • 此时就能看到标准的 四次挥手了!!!

在这里插入图片描述

相关文章:

【Linux网络#17】TCP全连接队列与tcpdump抓包

一、TCP 相关实验 测试 1. Listen 的第二个参数 LISTEN(2) Linux Programmers Manual NAMElisten - listen for connections on a socketSYNOPSIS#include <sys/types.h&g…...

JVM——Java对象的内存布局

Java对象的内存布局 在Java程序中&#xff0c;对象的内存布局是一个关键的底层概念。它不仅影响着对象的创建、使用和销毁的效率&#xff0c;也对垃圾回收、并发控制等机制有着深远的影响。下面我们将深入探讨Java对象的内存布局&#xff0c;包括对象的构成、内存分配、压缩指…...

USB资料摘录for后期,bus hound使用

一、STM32F105 USB调试:专家级错误分析与调试技巧: 在实时操作系统(RTOS)中进行USB调试时,开发者需要考虑任务调度、中断优先级和资源共享等问题。STM32F105在支持RTOS的环境中调试USB,应重点分析USB驱动与RTOS内核之间的交互,以及如何避免可能的竞态条件。 在商业级应用…...

防止交叉验证中的数据泄露:提升模型在实际环境中的性能

防止交叉验证中的数据泄露&#xff1a;提升模型在实际环境中的性能 你刚刚完成了一个机器学习模型的训练&#xff0c;其验证准确率达到了95%。交叉验证结果显示性能稳定&#xff0c;项目相关方对此表示认可&#xff0c;正准备将模型部署到生产环境。但是现实情况却令人沮丧——…...

Debezium TableSchemaBuilder详解

Debezium TableSchemaBuilder详解 1. 类的作用与功能 1.1 核心作用 TableSchemaBuilder是Debezium中负责构建表Schema的核心类,主要功能包括: Schema构建:将数据库表结构转换为Kafka Connect的Schema定义主键处理:生成表的主键Schema值Schema处理:生成表的非主键字段Sc…...

25:三大分类器原理

1.分类的逻辑&#xff1b; 2.统计学与数据分析。 ************************ Mlp 多层感知系统 GMM 高斯混合模型-极大似然估计法 SVM 支持向量机建立一个超平面作为决策曲面&#xff0c;使得正例和反例的隔离边界最大化 Knn 1.MLP整个模型就是这样子的&#xff0c;上面…...

osquery在网络安全入侵场景中的应用实战(二)

背景 上次写了osquery在网络安全入侵场景中的应用实战(一)结果还不错,这次篇目二再增加一些场景。osquery主要解决的时员工被入侵之后电脑该如何溯源取证的问题。通常EDR会有日志,但是不会上报全量的日志。发现机器有恶意文件需要上级取证的时候,往往是比较麻烦的,会有这…...

排序用法(Arrays.sort)

排序范围​​&#xff1a; 对 res 数组中索引从 ​​0到4​​ 的行进行排序&#xff08;因为结束索引5不包含&#xff09;相当于排序 res[0] 到 res[4] 这5行 ​​比较规则​​&#xff1a; o1 和 o2 是二维数组中的两行&#xff08;如 [8,2] 和 [6,7]&#xff09;o1[0] - o2[…...

2025年最新Linux的Redis主从集群搭建

一&#xff1a;概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的键值存储系统&#xff0c;通常被用作数据库、缓存或消息中间件。它以内存存储为主&#xff0c;支持多种数据结构&#xff0c;并具备持久化、高可用、分布式等特性&#xff0c;…...

Oracle OCP认证考试考点详解083系列09

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 41. 第41题&#xff1a; 题目 解析及答案&#xff1a; 关于应用程序容器&#xff0c;以下哪三项是正确的&#xff1f; A) 它可以包含单个…...

走出 Demo,走向现实:DeepSeek-VL 的多模态工程路线图

目录 一、引言&#xff1a;多模态模型的关键转折点 &#xff08;一&#xff09;当前 LMM 的三个关键挑战 1. 数据的真实性不足 2. 模型设计缺乏场景感知 3. 语言能力与视觉能力难以兼顾 &#xff08;二&#xff09;DeepSeek-VL 的根本出发点&#xff1a;以真实任务为锚点…...

Kotlin 作用域函数全解析:let、run、with、apply、also 应该怎么选?

Kotlin 提供了一套优雅的“作用域函数”&#xff08;Scope Functions&#xff09;&#xff0c;包括&#xff1a;let、run、with、apply 和 also。它们看起来相似&#xff0c;行为上也有交集&#xff0c;但却各有侧重。掌握它们的使用场景&#xff0c;不仅能让代码更简洁&#x…...

Python 矩阵运算:从理论到实践

Python 矩阵运算&#xff1a;从理论到实践 在数据分析、机器学习以及科学计算等诸多领域&#xff0c;矩阵运算均扮演着极为重要的角色。借助 Python 的 NumPy 库&#xff0c;我们可以便捷地实现各类矩阵运算。本文将深入探讨矩阵运算的数学原理&#xff0c;并通过实例演示如何…...

系统架构-层次式架构设计

层次式体系结构是最通用的架构&#xff0c;大部分的应用会分成表现层&#xff08;展示层&#xff09;、中间层&#xff08;业务层&#xff09;、数据访问层&#xff08;持久层&#xff09;和数据层 表现层架构设计 使用XML设计表现层 使用UIP框架设计表现层&#xff0c;UIP将…...

《Python星球日记》第29天:Flask进阶

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏:《Python星球日记》,限时特价订阅中ing 目录 一、重温 Flask 框架二、路由与视图1. 动态路由2. 路由装饰器三、模板渲染1. Jinja2 模板语法2.…...

Baklib知识中台:智能服务架构新实践

智能服务架构四库体系 Baklib 知识中台的核心竞争力源于其独创的四库体系架构设计。该体系通过知识资源库、业务场景库、智能模型库和服务规则库的有机联动&#xff0c;构建起覆盖知识全生命周期的管理闭环。其中&#xff0c;知识资源库依托自然语言处理技术实现多源异构数据的…...

CBAM透视镜:穿透软件架构成本迷雾的评估范式

文章目录 一、引言二、CBAM 基础理论2.1 CBAM 的定义与概念2.2 CBAM 的核心原理2.2.1 成本效益分析的基本逻辑2.2.2 定量化决策过程 2.3 CBAM 与其他软件架构评估方法的比较2.3.1 与 ATAM 对比2.3.2 与 SAAM 对比 三、CBAM 在软件架构中的应用流程3.1 确定评估目标3.2 列出架构…...

macbook install chromedriver

# 打开 Chrome 访问以下地址查看版本 chrome://version/# 终端查看版本号 (示例输出: 125.0.6422.113) /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --version测试&#xff1a;...

Java 一战式学习指南,很详细

java基础 一、简介 1.1 JDK Java Develop Kit : Java的开发包&#xff0c;包含了Java的类库、执行Java所需的允许环境、各种开发辅助工具等... JDK 分为 Oracle JDK 和 Open JDK &#xff0c;Oracle JDK需要商业许可证&#xff0c;是收费的。Open JDK 则是免费的。 1.2 Ja…...

从零开始开发纯血鸿蒙应用之NAPI

从零开始开发纯血鸿蒙应用 〇、前言一、解耦良器——Adapter二、详学 NAPI1、注册自定义的 NAPI1.1、Index.d.ts1.2、napi_property_descriptor 数组 2、读取参数2.1、读取字符类型数据2.1、读取数字类型 3、封装返回值4、C/C 调用 ArkTS 方法5、自定义 C 类的透传 三、总结坑点…...

立夏三候:蝼蝈鸣,蚯蚓出,王瓜生

今&#xff08;5月5日&#xff09;天是立夏节气&#xff0c;尽管本“人民&#xff0b;体验官”已是最畏惧感到气喘吁吁这夏天气候之老龄人&#xff0c;但还是要推广人民日报官方微博文化产品《文化中国行看立夏节气》。 人民微博着重提示“立夏三候”三个方面&#xff1a;“一候…...

Nuxt3还能用吗?

Nuxt3还能用吗&#xff1f; 前一段时间&#xff0c;我完成了整个产品&#xff0c;从Nuxt到Next的迁移&#xff0c;因为面临了一些在框架层面就无法解决的问题。 payload json化 在所有的的Nuxt中&#xff0c;我们都能看到有这样一个东西。 其实有这个东西也很正常&#xff0…...

专业课复习笔记 4

前言 实际上对于我的考研来说&#xff0c;最重要的两门就是数学和专业课。所以从今天开始&#xff0c;我尽可能多花时间学习数学和专业课。把里面的知识和逻辑关系理解清楚&#xff0c;把常考的内容练习透彻。就这样。 寻址方式 立即数寻址 操作数在指令里面直接提供了。 …...

[人机交互]交互设计

零.本章的主要目标 本章主要目标总结 区分良与非良交互设计&#xff0c;突出产品可用性差异阐述交互设计与HCI及其他领域的关系解释可用性概念概述交互设计过程涉及的内容概述交互设计中所使用的指南形式从可用性目标和原理角度&#xff0c;评估并解释产品的成败 一.什么是交…...

LeetCode 热题 100 17. 电话号码的字母组合

LeetCode 热题 100 | 17. 电话号码的字母组合 大家好&#xff0c;今天我们来解决一道经典的算法题——电话号码的字母组合。这道题在 LeetCode 上被标记为中等难度&#xff0c;要求给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。下面我将详细讲解解…...

【从零开始学习微服务 | 第一篇】单体项目到微服务拆分实践

目录 引言 一、选择聚合结构进行拆分的优势 二、微服务模块创建步骤 &#xff08;一&#xff09;引入 pom 文件与修改 &#xff08;二&#xff09;创建 Spring Boot 启动类 &#xff08;三&#xff09;搭建基本包结构 三、配置文件的引入与调整 四、业务代码的引入与注意…...

微前端qiankun动态路由权限设计与数据通信方案

思路&#xff1a; 权限控制中心化&#xff1a;主应用负责统一的管理权限&#xff0c;子路由上报路由信息 动态路由加载&#xff1a;根据用户权限动态注册可用路由 数据通信机制 主应用和子应用&#xff1a;通过qiankun提供的props和全局状态 子应用和子应用&#xff1a;通过…...

VTK 数据读取/写入类介绍

概述 VTK提供了多种数据读取和写入类,支持各种格式的输入输出操作,包括图像数据、多边形数据、结构化/非结构化网格数据等。 常用VTK读取类 vtkSTLReader 读取STL格式文件 属性: FileName - 要读取的STL文件名 方法: SetFileName(const char*) - 设置文件名 GetFileName…...

41.寻找缺失的第一个正数:原地哈希算法详解

文章目录 引言问题描述方法思路&#xff1a;原地哈希算法算法步骤 完整代码实现关键代码解析复杂度分析示例说明总结 引言 在算法面试和数据处理中&#xff0c;寻找缺失的第一个正数是一个经典问题。题目要求给定一个未排序的整数数组&#xff0c;找到其中缺失的最小正整数&am…...

项目实战-基于信号处理与SVM机器学习的声音情感识别系统

目录 一.背景描述 二.理论部分 三.程序设计 编程思路 流程图 1.信号部分 创建数据 generate_samples.py 头文件 生成函数 generate_emotion_sample 传入参数 存储路径 生成参数 创建基础正弦波信号 调制基础正弦波 对于愤怒可以增加噪声 归一化信号 存储 主函…...

基于Docker的MongoDB环境搭建:从零开始的完整实践指南

在现代应用开发中,容器化技术已成为构建可移植、易维护的服务环境的标准方案。MongoDB作为NoSQL数据库的代表,与Docker结合后能够显著提升部署效率。本文将深入解析如何通过Docker搭建安全可靠的MongoDB环境,涵盖基础配置、数据持久化、权限管理及安全加固等核心环节。 一、…...

C++ 类与对象(下)—— 进阶特性与底层机制解析(构造函数初始化,类型转换,static成员,友元,内部类,匿名对象)

一、构造函数初始化列表&#xff1a;给成员变量 “精准出生证明” 在 C 中&#xff0c;构造函数对成员变量的初始化方式有 初始化列表 和 函数体内赋值 两种。初始化列表是构造函数的一个重要特性&#xff0c;它允许在对象创建时对成员变量进行初始化。与在构造函数体内赋值不同…...

项目生成日志链路id,traceId

Trace 1. 注册filter package com.sc.account.config;import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public cla…...

SQL常见误区

查询的顺序 书写顺序 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后条件列表 ORDER BY 排序字段列表。。他们的加载顺序 逻辑处理实际顺序 常见错误 在 WHERE 中使用 SELECT 的别名 sql – 错误示例&#xff08;WHERE 中不能使用别名…...

android zxing QrCode 库集成转竖屏适配问题

由于zxing 这个库使用比较广泛&#xff0c;所以大家也都遇到这个问题了&#xff0c;甚至最早可以追溯到十年前甚至更早&#xff0c;所以原创是谁已经无法找到&#xff0c;表明转载又需要填原文链接&#xff0c;就腆着脸标个原创了&#xff0c;不过的确不是我的原创&#xff0c;…...

实验4 mySQL查询和视图

一、实验目的 掌握SELECT语句的基本语法多表连接查询GROUP BY的使用方法。ORDER BY的使用方法。 二、实验步骤、内容、结果 实验内容&#xff1a; 实验4.1数据库的查询 目的与要求 (1)掌握SELECT语句的基本语法。 (2)掌握子查询的表示。 (3)掌握连接查询的表示。 (4)掌…...

解决用Deveco device tool无法连接local pc

原文链接&#xff1a;https://kashima19960.github.io/2025/05/05/openharmony/解决用Deveco%20device%20tool无法连接local%20pc/ 问题描述 WindowsUbuntu 环境下DevEco tool upload Hi3681开发 烧录 Local PC 箭头红一下&#xff0c;又绿了 用Deveco device tool进行upload…...

Google-chrome版本升级后sogou输入法不工作了

背景&#xff1a; 笔记本Thinkpad E450&#xff0c;操作系统Ubuntu 24.04.2 LTS&#xff0c;Chrome浏览器版本135.0.7049.114-1&#xff0c;Edge浏览器版本131.0.2903.99-1&#xff0c;输入法Sogou版本4.2.1.145 现象&#xff1a; - **正常场景**&#xff1a;Edge中可通过Ctrl…...

C++ 检查某个点是否存在于圆扇区内(Check whether a point exists in circle sector or not)

我们有一个以原点 (0, 0) 为中心的圆。作为输入&#xff0c;我们给出了圆扇区的起始角度和圆扇区的大小&#xff08;以百分比表示&#xff09;。 例子&#xff1a; 输入&#xff1a;半径 8 起始角 0 百分比 12 x 3 y 4 输出&am…...

电脑怎么分屏操作?

快捷键分屏 &#xff1a; 在打开两个窗口后&#xff0c;选中一个窗口&#xff0c;按下 “Windows 键 →” 键&#xff0c;该窗口会自动移动到屏幕右侧并占据一半空间&#xff0c;再点击需要分屏的窗口&#xff0c;即可完成分屏。若想恢复窗口为全屏&#xff0c;只需再次按下 …...

深度学习:智能助理从技术演进到全民普惠

在数字化浪潮席卷全球的今天&#xff0c;智能助理已成为人们生活与工作中不可或缺的伙伴。从简单的语音应答到如今具备复杂认知与交互能力&#xff0c;深度学习技术的持续突破&#xff0c;正推动智能助理行业迈向全新高度。深入探究其行业发展、现状、技术演进与实践&#xff0…...

哈希算法、搜索算法与二分查找算法在 C# 中的实现与应用

在计算机科学中&#xff0c;哈希算法、搜索算法和二分查找算法是三个非常基础且常用的概念。它们分别在数据存储、数据查找、以及高效检索等场景中起着至关重要的作用。在 C# 中&#xff0c;这些算法的实现和使用也十分简便。本文将详细讲解这三种算法的原理、应用以及 C# 中的…...

优化02-执行计划

Oracle 的执行计划&#xff08;Execution Plan&#xff09;是数据库优化器&#xff08;Optimizer&#xff09;为执行 SQL 语句而选择的操作路径和资源分配方案的详细描述。它记录了数据库如何访问表、索引、连接数据以及执行排序、过滤等操作的步骤。理解执行计划是性能调优的核…...

FreeRTOS菜鸟入门(十一)·信号量·二值、计数、递归以及互斥信号量的区别·优先级翻转以及继承机制详解

目录 1. 信号量的基本概念 2. 分类 2.1 二值信号量 2.2 计数信号量 2.3 互斥信号量 2.4 递归信号量 3. 应用场景 3.1 二值信号量 3.2 计数信号量 3.3 互斥信号量 3.4 递归信号量 4. 运作机制 4.1 二值信号量 4.2 计数信号量 4.3 互斥信号量 4.4…...

C++ -- 内存管理

C --内存管理 1. C/C内存分布2. C中动态内存管理3. C中动态内存管理4. 面对自定义类型5. operator new和operator delete6. new和delete的实现原理6.1 内置类型6.2 自定义类型 7. 定位new&#xff08;placement new&#xff09;7.1 底层机制7.2 本质 1. C/C内存分布 2. C中动态…...

基于muduo库实现高并发服务器

文章目录 一、项目介绍二、HTTP服务器1.概念2.Reactor模型2.1单Reactor单线程&#xff1a;单I/O多路复用业务处理2.2单Reactor多线程&#xff1a;单I/O多路复用线程池&#xff08;业务处理&#xff09;2.3多Reactor多线程&#xff1a;多I/O多路复用线程池&#xff08;业务处理&…...

开源PDF解析工具Marker深度解析

开源PDF解析工具Marker深度解析 检索增强生成&#xff08;RAG&#xff09;系统的第一步就是做 pdf 解析&#xff0c;从复杂多样的 pdf 中提取出干净准确的文本内容。现有的最优秀的开源工具有两个&#xff1a;Marker 和 MinerU。因为 Marker 是个人开发者做的&#xff0c;文档…...

Redis的内存淘汰机制

Redis的内存淘汰机制和过期策略是2个完全不同的机制&#xff0c; 过期策略指的是使用那种策略来删除过期键&#xff0c;Redis的内存淘汰机制是指&#xff1a;当Redis的运行内存已经超过设置的最大运行内存时&#xff0c;采用什么策略来删除符合条件的键值对&#xff0c;以此来保…...

我国“东数西算”工程对数据中心布局的长期影响

首席数据官高鹏律师团队 我国“东数西算”工程作为国家级战略&#xff0c;旨在优化全国算力资源配置&#xff0c;推动数字经济发展&#xff0c;其对数据中心布局的长期影响主要体现在以下几个方面&#xff1a; 1. 区域协调与资源优化配置 东部与西部分工明确&#xff1a;东部…...

CPT204 Advanced Obejct-Oriented Programming 高级面向对象编程 Pt.10 二叉搜索树

文章目录 1.二叉树&#xff08;Binary Trees&#xff09;1.1 二叉搜索树&#xff08;Binary Search Tree&#xff0c;简称BST&#xff09;1.1.1 插入操作1.1.2 搜索操作1.1.3 树的遍历&#xff08;Tree Traversal&#xff09;1.1.3.1 前序遍历&#xff08;Preorder Traversal&a…...