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

【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)

【Linux】【网络】UDP打洞–>不同子网下的客户端和服务器通信(未成功版)

上次说基于UDP的打洞程序改了五版一直没有成功,要写一下问题所在,但是我后续又查询了一些资料,成功实现了,这次先写一下未成功的逻辑,我认为未成功的排查错误的部分也很重要,如果想直接看成功的可以直接看我的下一篇文章。

首先 基于上篇文章的UDP打洞逻辑
这里直接将图贴出来:
在这里插入图片描述
我的逻辑思路:(ps:会把代码贴到最后面。)

逻辑梳理

1 服务器端(server.c)

  1. 监听与接收注册
    • 服务器创建 UDP 套接字并绑定到固定端口(5050)。
    • 依次调用 recvfrom() 接收两个客户端(先后为 C1 和 C2)的注册消息,获取各自的源地址(即 NAT 映射后的公网 IP 和端口)。
  2. 地址交换
    • 服务器把 C2 的公网地址(IP 和端口)格式化成字符串(用“^”分隔)发送给 C1。
    • 同样把 C1 的地址发送给 C2。
  3. 后续处理
    • 服务器完成地址交换后退出(没有额外发送探测包)。

客户端 C1(UDPClientcc1.c)

  1. 两个套接字
    • 使用一个套接字(sockS)与服务器通信,另一个(sockC)用于后续对等通信,并绑定到固定端口(6003)。
  2. 注册阶段
    • C1 向服务器发送注册消息(“I am C1”)。
    • 接收服务器返回的字符串,解析出对方地址信息(格式 “ip^port”),存入 oppositeSideAddr。
  3. P2P 交互循环
    • 在循环中,每隔 500ms 使用 sockC 向 oppositeSideAddr 发送数据(keep-alive/消息),并尝试接收对方回复。

客户端 C2(UDPClientcc2.c)

  1. 逻辑与 C1 类似
    • 使用两个套接字,一个与服务器通信(sockS),一个用于 P2P(sockC),绑定固定端口(6002)。
    • 向服务器发送注册消息(“I am C2”),接收并解析服务器返回的对方地址信息,存入 oppositeSideAddr。
    • 进入循环,每隔 500ms 向 oppositeSideAddr 发送数据,并等待回复。

执行结果

服务器:
在这里插入图片描述

客户端c1:
在这里插入图片描述
客户端c2:
在这里插入图片描述

可以看到c1,c2 一直在向从服务器获取的公网ip和端口发送数据 但是一直未收到对端回复。
服务器在向双方发送数据后就直接退出了。

排查问题:

考虑可能存在的问题并逐步排查:

  1. 服务器配置问题
    • 确保服务器S正确交换了双方的公网IP和端口信息,并且客户端解析无误。
  2. 防火墙设置
    • 检查云服务器、客户端以及NAT设备的防火墙是否允许UDP流量通过,特别是目标端口是否开放。
    • 也需要确保双方的UDP打洞程序所在主机允许接收来自对端的UDP数据包。
  3. NAT映射问题
    • 可能两端的NAT设备类型不支持直接UDP打洞,或映射策略比较严格(例如对称NAT)。
    • 您可以检查客户端所在网络的NAT类型,尝试在不同网络环境下测试。
  4. 端口绑定和映射问题
    • 确认代码中绑定的本地端口(6003、6002)与NAT映射结果是否符合预期。
    • 有些NAT设备可能会复用端口或调整外部映射,导致双方看到相同的公网端口,从而影响打洞效果。
  5. 代码逻辑问题
    • 您的代码中目前只是不断发送数据包,但并未实现对收到数据包进行有效处理。如果对端也没有收到数据包,可能是由于发送方向NAT设备发送的数据包没有成功映射到对端。

1 服务器是否正确交换了双方的ip和端口

这个测试结果是我第四版的结果在里面已经打印出来对应的ip,端口我这边对比了并未出现问题 你们可以再看看上面的图片
结论:正常

2防火墙设置

本地防火墙: 检查客户端和服务器上的防火墙状态(使用 ufw status、iptables -L 等命令),确认UDP目标端口是否被允许。
云防火墙: 登录云服务器控制台或路由器管理界面,检查是否设置了安全组或防火墙规则,确保允许相应的UDP流量(包括注册端口和通信端口)。

2.1 本地防火墙

本地防火墙未打开
在这里插入图片描述

2.2 云服务器

防火墙对应端口已开启
在这里插入图片描述
结论:正常

3 抓包查看数据包是否发送出去

在Ubuntu下,使用抓包工具来监控和分析网络数据包的流向,常用的工具包括 tcpdump(命令行)和 Wireshark(图形界面)。


3.1. 使用 tcpdump

安装:

sudo apt-get update
sudo apt-get install tcpdump

基本用法:

  • 抓取所有数据包:

    sudo tcpdump -i eth0
    

    其中 eth0 是您要监控的网络接口,可以通过命令 ifconfig 查看接口名称。
    我的就是ens33
    在这里插入图片描述

  • 过滤特定协议和端口:

    例如,抓取UDP数据包:

    sudo tcpdump -i ens33 udp
    

    抓取目的端口为5050的UDP数据包:

    sudo tcpdump -i ens33 udp port 5050
    

    在这里插入图片描述在这里插入图片描述
    抓包发现数据发送出去了

3 NAT映射问题

使用 stun 工具

1. 安装 stun 客户端:
在 Ubuntu系统上运行:

sudo apt update
sudo apt install stun-client -y

2. 运行 STUN 客户端测试 NAT 类型

stun stun.l.google.com

或者:

stun stun.sipgate.net

这是我的结果
在这里插入图片描述

  • Independent Mapping(独立映射):
    每个内部端口的映射是独立的,即无论目标地址如何变化,都保持相同的映射。对 UDP 打洞来说,这通常是有利的。

  • Independent Filter(独立过滤):
    外部数据包只要符合映射的端口,就会被放行,与发送目标无关。这意味着只要内网设备先发起通信,外部的回复通常能通过 NAT 设备到达内网。

  • Random Port(随机端口):
    每个新连接可能会被 NAT 分配一个随机的外部端口,这可能会导致端口映射不固定。为了保持连接,客户端需要持续发送数据包以维持映射。

  • No Hairpin:
    表示 NAT 不支持内部设备通过公网地址直接访问同一 NAT 内的其他设备(NAT 回环)。这通常对 UDP 打洞影响不大,因为 C1 和 C2 是处于不同 NAT 或在不同网络下。

  • Return value is 0x000012:
    表示 STUN 客户端检测成功,但没有显示映射的端口详细信息,通常这意味着端口由 NAT 设备随机分配。

这个结果说明 NAT 环境是相对有利于 UDP 打洞的(非对称 NAT),但由于随机端口的特性,客户端必须持续发送保持 UDP 映射(Keep-Alive)。

3. NAT 类型

  • Full Cone NAT(全锥形 NAT) ✅ UDP 打洞最容易成功
  • Restricted Cone NAT(受限锥形 NAT) ✅ 需要双向数据包打洞
  • Port-Restricted Cone NAT(端口受限锥形 NAT) ⚠ 可能无法直接打洞
  • Symmetric NAT(对称 NAT) ❌ UDP 打洞几乎不可能成功

证明NAT映射支持打洞

最后怀疑问题出在代码逻辑上,服务器返回的端口虽然正确,但 NAT设备 在一段时间后修改了端口映射,或者端口映射被丢弃,导致 C1 发送到错误端口。因此后续需要修改端口。

server.c

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define DEFAULT_PORT 5050
#define BUFFER_SIZE 100int main() {// server即外网服务器int serverPort = DEFAULT_PORT;int serverListen;struct sockaddr_in serverAddr;// 建立监听socketserverListen = socket(AF_INET, SOCK_DGRAM, 0);if (serverListen == -1) {perror("socket() failed");return -1;}serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(serverPort);serverAddr.sin_addr.s_addr = INADDR_ANY;if (bind(serverListen, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {perror("bind() failed");return -1;}// 接收来自客户端的连接,source1即先连接到S的客户端C1struct sockaddr_in sourceAddr1;socklen_t sourceAddrLen1 = sizeof(sourceAddr1);char bufRecv1[BUFFER_SIZE];int len;len = recvfrom(serverListen, bufRecv1, sizeof(bufRecv1), 0, (struct sockaddr *)&sourceAddr1, &sourceAddrLen1);if (len == -1) {perror("recvfrom() failed");return -1;}bufRecv1[len] = '\0';printf("C1 IP:[%s],PORT:[%d]\n", inet_ntoa(sourceAddr1.sin_addr), ntohs(sourceAddr1.sin_port));// 接收来自客户端的连接,source2即后连接到S的客户端C2struct sockaddr_in sourceAddr2;socklen_t sourceAddrLen2 = sizeof(sourceAddr2);char bufRecv2[BUFFER_SIZE];len = recvfrom(serverListen, bufRecv2, sizeof(bufRecv2), 0, (struct sockaddr *)&sourceAddr2, &sourceAddrLen2);if (len == -1) {perror("recvfrom() failed");return -1;}bufRecv2[len] = '\0';printf("C2 IP:[%s],PORT:[%d]\n", inet_ntoa(sourceAddr2.sin_addr), ntohs(sourceAddr2.sin_port));// 向C1发送C2的外网ip和portchar bufSend1[BUFFER_SIZE];// bufSend1中存储C2的外网ip和portmemset(bufSend1, '\0', sizeof(bufSend1));char *ip2 = inet_ntoa(sourceAddr2.sin_addr);// C2的ipchar port2[10];// C2的portsnprintf(port2, sizeof(port2), "%d", ntohs(sourceAddr2.sin_port));snprintf(bufSend1, sizeof(bufSend1), "%s^%s", ip2, port2);len = sendto(serverListen, bufSend1, strlen(bufSend1), 0, (struct sockaddr *)&sourceAddr1, sourceAddrLen1);if (len == -1) {perror("sendto() failed");return -1;} else {printf("send() byte:%d\n", len);}// 向C2发送C1的外网ip和portchar bufSend2[BUFFER_SIZE];// bufSend2中存储C1的外网ip和portmemset(bufSend2, '\0', sizeof(bufSend2));char *ip1 = inet_ntoa(sourceAddr1.sin_addr);// C1的ipchar port1[10];// C1的portsnprintf(port1, sizeof(port1), "%d", ntohs(sourceAddr1.sin_port));snprintf(bufSend2, sizeof(bufSend2), "%s^%s", ip1, port1);len = sendto(serverListen, bufSend2, strlen(bufSend2), 0, (struct sockaddr *)&sourceAddr2, sourceAddrLen2);if (len == -1) {perror("sendto() failed");return -1;} else {printf("send() byte:%d\n", len);}// server的中间人工作已完成,退出即可,剩下的交给C1与C2相互通信close(serverListen);return 0;
}

client1.c

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>#define PORT 6003
#define BUFFER_SIZE 100int main(int argc, char* argv[]) {struct sockaddr_in serverAddr;struct sockaddr_in thisAddr;thisAddr.sin_family = AF_INET;thisAddr.sin_port = htons(PORT);thisAddr.sin_addr.s_addr = INADDR_ANY;if (argc < 3) {printf("Usage: UDPClient1 <Server IP address> <Server Port>\n");return -1;}int sockS = socket(AF_INET, SOCK_DGRAM, 0);if (sockS == -1) {perror("socket() failed");return -1;}if (bind(sockS, (struct sockaddr *)&thisAddr, sizeof(thisAddr)) == -1) {perror("bind() failed");return -1;}int sockC = socket(AF_INET, SOCK_DGRAM, 0);if (sockC == -1) {perror("socket() failed");return -1;}// 允许端口复用int optval = 1;setsockopt(sockC, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));// 绑定固定端口 6003struct sockaddr_in bindAddr;bindAddr.sin_family = AF_INET;bindAddr.sin_port = htons(6003);bindAddr.sin_addr.s_addr = INADDR_ANY;bind(sockC, (struct sockaddr *)&bindAddr, sizeof(bindAddr));char bufSend[] = "I am C1";char bufRecv[BUFFER_SIZE];memset(bufRecv, '\0', sizeof(bufRecv));struct sockaddr_in sourceAddr;socklen_t sourceAddrLen = sizeof(sourceAddr);struct sockaddr_in oppositeSideAddr;int len;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(atoi(argv[2]));serverAddr.sin_addr.s_addr = inet_addr(argv[1]);len = sendto(sockS, bufSend, sizeof(bufSend), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));if (len == -1) {perror("sendto() to S failed");return -1;}printf("C1 sent registration packet to server S.\n");len = recvfrom(sockS, bufRecv, sizeof(bufRecv), 0, (struct sockaddr *)&sourceAddr, &sourceAddrLen);if (len == -1) {perror("recvfrom() from S failed");return -1;}bufRecv[len] = '\0';printf("C1 received from S: %s\n", bufRecv);close(sockS);char ip[20];char port[10];int i = 0;while (i < strlen(bufRecv) && bufRecv[i] != '^') {ip[i] = bufRecv[i];i++;}ip[i] = '\0';int j = 0;i++;while (i < strlen(bufRecv)) {port[j++] = bufRecv[i++];}port[j] = '\0';oppositeSideAddr.sin_family = AF_INET;oppositeSideAddr.sin_port = htons(atoi(port));oppositeSideAddr.sin_addr.s_addr = inet_addr(ip);int flags = fcntl(sockC, F_GETFL, 0);fcntl(sockC, F_SETFL, flags | O_NONBLOCK);printf("C1 will now try to communicate directly with C2 at %s:%s\n", ip, port);int attempts = 0;while (1) {usleep(500000);  // 500ms 发送一次len = sendto(sockC, bufSend, sizeof(bufSend), 0, (struct sockaddr *)&oppositeSideAddr, sizeof(oppositeSideAddr));if (len == -1) {perror("sendto() to C2 failed");} else {printf("Sent keep-alive UDP packet to %s:%d\n", inet_ntoa(oppositeSideAddr.sin_addr), ntohs(oppositeSideAddr.sin_port));}len = recvfrom(sockC, bufRecv, sizeof(bufRecv), 0, (struct sockaddr *)&sourceAddr, &sourceAddrLen);if (len == -1) {if (errno == EAGAIN || errno == EWOULDBLOCK) {attempts++;if (attempts % 10 == 0) {printf("No response from C2 after 5 seconds. Retrying...\n");}continue;} else {perror("recvfrom() failed");break;}} else {bufRecv[len] = '\0';printf("C1 received from C2 [%s:%d]: %s\n", inet_ntoa(sourceAddr.sin_addr), ntohs(sourceAddr.sin_port), bufRecv);attempts = 0;  // 成功收到数据,重置重试计数}}close(sockC);return 0;
}

client2.c

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>#define PORT 6002
#define BUFFER_SIZE 100int main(int argc, char* argv[]) {struct sockaddr_in serverAddr;struct sockaddr_in thisAddr;thisAddr.sin_family = AF_INET;thisAddr.sin_port = htons(PORT);thisAddr.sin_addr.s_addr = INADDR_ANY;if (argc < 3) {printf("Usage: UDPClient2 <Server IP address> <Server Port>\n");return -1;}int sockS = socket(AF_INET, SOCK_DGRAM, 0);if (sockS == -1) {perror("socket() failed");return -1;}if (bind(sockS, (struct sockaddr *)&thisAddr, sizeof(thisAddr)) == -1) {perror("bind() failed");return -1;}int sockC = socket(AF_INET, SOCK_DGRAM, 0);if (sockC == -1) {perror("socket() failed");return -1;}// 允许端口复用int optval = 1;setsockopt(sockC, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));// 绑定固定端口 6002struct sockaddr_in bindAddr;bindAddr.sin_family = AF_INET;bindAddr.sin_port = htons(6002);bindAddr.sin_addr.s_addr = INADDR_ANY;bind(sockC, (struct sockaddr *)&bindAddr, sizeof(bindAddr));char bufSend[] = "I am C2";char bufRecv[BUFFER_SIZE];memset(bufRecv, '\0', sizeof(bufRecv));struct sockaddr_in sourceAddr;socklen_t sourceAddrLen = sizeof(sourceAddr);struct sockaddr_in oppositeSideAddr;int len;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(atoi(argv[2]));serverAddr.sin_addr.s_addr = inet_addr(argv[1]);len = sendto(sockS, bufSend, sizeof(bufSend), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr));if (len == -1) {perror("sendto() to S failed");return -1;}printf("C2 sent registration packet to server S.\n");len = recvfrom(sockS, bufRecv, sizeof(bufRecv), 0, (struct sockaddr *)&sourceAddr, &sourceAddrLen);if (len == -1) {perror("recvfrom() from S failed");return -1;}bufRecv[len] = '\0';printf("C2 received from S: %s\n", bufRecv);close(sockS);char ip[20];char port[10];int i = 0;while (i < strlen(bufRecv) && bufRecv[i] != '^') {ip[i] = bufRecv[i];i++;}ip[i] = '\0';int j = 0;i++;while (i < strlen(bufRecv)) {port[j++] = bufRecv[i++];}port[j] = '\0';oppositeSideAddr.sin_family = AF_INET;oppositeSideAddr.sin_port = htons(atoi(port));oppositeSideAddr.sin_addr.s_addr = inet_addr(ip);int flags = fcntl(sockC, F_GETFL, 0);fcntl(sockC, F_SETFL, flags | O_NONBLOCK);printf("C2 will now try to communicate directly with C1 at %s:%s\n", ip, port);int attempts = 0;while (1) {usleep(500000);  // 500ms 发送一次len = sendto(sockC, bufSend, sizeof(bufSend), 0, (struct sockaddr *)&oppositeSideAddr, sizeof(oppositeSideAddr));if (len == -1) {perror("sendto() to C1 failed");} else {printf("Sent keep-alive UDP packet to %s:%d\n", inet_ntoa(oppositeSideAddr.sin_addr), ntohs(oppositeSideAddr.sin_port));}len = recvfrom(sockC, bufRecv, sizeof(bufRecv), 0, (struct sockaddr *)&sourceAddr, &sourceAddrLen);if (len == -1) {if (errno == EAGAIN || errno == EWOULDBLOCK) {attempts++;if (attempts % 10 == 0) {printf("No response from C1 after 5 seconds. Retrying...\n");}continue;} else {perror("recvfrom() failed");break;}} else {bufRecv[len] = '\0';printf("C2 received from C1 [%s:%d]: %s\n", inet_ntoa(sourceAddr.sin_addr), ntohs(sourceAddr.sin_port), bufRecv);attempts = 0;  // 成功收到数据,重置重试计数}}close(sockC);return 0;
}

相关文章:

【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)

【Linux】【网络】UDP打洞–>不同子网下的客户端和服务器通信&#xff08;未成功版&#xff09; 上次说基于UDP的打洞程序改了五版一直没有成功&#xff0c;要写一下问题所在&#xff0c;但是我后续又查询了一些资料&#xff0c;成功实现了&#xff0c;这次先写一下未成功的…...

C# 中的Action和Func是什么?Unity 中的UnityAction是什么? 他们有什么区别?

所属范围&#xff1a;Action 和 Func 是 C# 语言标准库中的委托类型&#xff0c;可在任何 C# 项目里使用&#xff1b;UnityAction 是 Unity 引擎专门定义的委托类型&#xff0c;只能在 Unity 项目中使用。 返回值&#xff1a;Action 和 UnityAction 封装的方法没有返回值&…...

SparkStreaming之03:容错、语义、整合kafka、Exactly-Once、ScalikeJDBC

SparkStreaming进阶 一 、要点:star:4.1 SparkStreaming容错4.1.1 SparkStreaming运行流程4.1.2 如果Executor失败&#xff1f;:star:4.1.3 如果Driver失败&#xff1f;4.1.4 数据丢失如何处理:star:4.1.5 当一个task很慢容错 :star:4.2 SparkSreaming语义4.3 SparkStreaming与…...

让单链表不再云里雾里

一日不见&#xff0c;如三月兮&#xff01;接下来与我一起创建单链表吧&#xff01; 目录 单链表的结构&#xff1a; 创建单链表&#xff1a; 增加结点&#xff1a; 插入结点&#xff1a; 删除结点&#xff1a; 打印单链表&#xff1a; 单链表查找&#xff1a; 单链表…...

Linux系统管理(十八)——Ubuntu Server环境下载安装图形化界面、英伟达显卡驱动、Cuda、cudnn、conda的深度学习环境

安装ubuntu系统 镜像源地址&#xff1a;https://ubuntu.com/download/server 安装镜像是最好联网&#xff0c;这样不需要自己配置网络地址&#xff0c;会自动生成动态地址 配置镜像源 在装系统时最好设置好镜像源地址 清华镜像源&#xff1a;https://mirrors.tuna.tsinghua.…...

深度学习的隐身术:详解 PyTorch nn.Dropout

前言 你是否遇到过这样的情况?训练时模型表现得像个学霸,准确率高得离谱,可一到测试集就原形毕露,像是考试作弊被抓包的学生,成绩一落千丈。这种现象叫过拟合,你的模型可能只是死记硬背了训练数据,并没有真正理解其中的模式。 别慌!解决过拟合的方法之一就是Dropout,…...

vscode工作区看不清光标

案例分析&#xff1a; 有的时候当我们把vscode的背景色设置成黑色或者默认黑色时 "workbench.colorTheme": "Visual Studio Dark"这时鼠标指针在非停留状态(指针移动时就看不清)&#xff0c;需要改下系统的鼠标指针设置&#xff0c;而不是vscode的光标设置…...

2025-03-04 学习记录--C/C++-PTA 习题5-4 使用函数求素数和

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>// 函数声明&#xff1a;判断一个数是…...

Open3D 学习指南 (持续学习)

本章仅为个人学习整理。 Open3D: https://www.open3d.org/ Github repo: https://github.com/isl-org/Open3D 1. 概述 Open3D 是一个开源库&#xff0c;旨在为 3D 数据处理提供高效且易用的工具。它由 Intel 开发和维护&#xff0c;支持多种 3D 数据处理任务&#xff0c;如…...

端口安全测试全方位指南:风险、流程与防护策略

在数字化时代&#xff0c;网络安全至关重要&#xff0c;而端口安全作为网络防护的前沿阵地&#xff0c;稍有疏忽就可能为恶意攻击者打开入侵的大门。以下为您详细阐述端口安全测试的全面流程、核心风险点、应对策略及防护建议。 一、测试前的周密筹备 &#xff08;一&#xf…...

3dsmax烘焙光照贴图然后在unity中使用

效果预览 看不清[完蛋&#xff01;] 实现步骤 使用 软件 软体名称地址photoshophttps://www.adobe.com/products/photoshop.htmlunity3Dhttps://unity.com/3dsmaxhttps://www.autodesk.com.cn/products/3ds-max/free-trialpacker-iohttps://www.uv-packer.com/HDR 贴图地址…...

GCN从理论到实践——基于PyTorch的图卷积网络层实现

Hi&#xff0c;大家好&#xff0c;我是半亩花海。图卷积网络&#xff08;Graph Convolutional Network, GCN&#xff09;是一种处理图结构数据的深度学习模型。它通过聚合邻居节点的信息来更新每个节点的特征表示&#xff0c;广泛应用于社交网络分析、推荐系统和生物信息学等领…...

Ollama存在安全风险的情况通报及解决方案

据清华大学网络空间测绘联合研究中心分析&#xff0c;开源跨平台大模型工具Ollama默认配置存在未授权访问与模型窃取等安全隐患。鉴于目前DeepSeek等大模型的研究部署和应用非常广泛&#xff0c;多数用户使用Ollama私有化部署且未修改默认配置&#xff0c;存在数据泄露、算力盗…...

大模型在高血压预测及围手术期管理中的应用研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 国内外研究现状 二、大模型预测高血压的原理与方法 2.1 常用大模型介绍 2.2 数据收集与预处理 2.3 模型训练与验证 三、术前风险预测与手术方案制定 3.1 术前风险因素分析 3.2 大模型预测术前风险的方法与结果 …...

网络安全rt是什么意思

1.什么时EDR :完全不同以往的端点被防护思路&#xff0c;而是通过云端威胁情报&#xff0c;机器学习&#xff0c;异常行为分析&#xff0c;攻击指示器等方式&#xff0c;主动发现来自外部或内部的安全威胁 。并进行自动化的阻止&#xff0c;取证&#xff0c;补救和溯源从而有效…...

数据结构篇—栈(stack)

一、引入 在数学史上有这样一个经典问题——汉诺塔问题。 通过动图演示我们发现每一个圆片的运动是什么样的呢&#xff1f; 我们发现&#xff0c;第一个放入的最大圆片将位于整个塔的最底端。所以若想将最大圆片拿出来&#xff0c;就得将压在它身上的所有圆片先按顺序取出才能将…...

python3.13安装教程【2025】python3.13超详细图文教程(包含安装包)

文章目录 前言一、python3.13安装包下载二、Python 3.13安装步骤三、Python3.13验证 前言 本教程将为你详细介绍 Python 3.13 python3.13安装教程&#xff0c;帮助你顺利搭建起 Python 3.13 开发环境&#xff0c;快速投身于 Python 编程的精彩实践中。 一、python3.13安装包下…...

动态内存分配

动态内存分配 1. malloc1.1函数原型1.2参数1.3特点1.4注意事项 2.calloc2.1函数原型2.2参数2.3特点2.4注意事项 3.realloc3.1函数原型3.2参数3.3特点3.4注意事项 4.free4.1 函数原型4.2参数4.3特点 结语 在 C 语言中&#xff0c;主要使用标准库函数 <stdlib.h> 中的几个函…...

物联网设备数据割裂难题:基于OAuth2.0的分布式用户画像系统设计!格行代理是不是套路?2025有什么比较好的副业?低成本的创业好项目有哪些?

一、行业基本面&#xff1a;双赛道增长逻辑验证 1.1 随身WiFi市场&#xff1a;场景红利与技术博弈 移动办公、户外直播等场景推动随身WiFi需求持续增长&#xff0c;格行核心的三网切换技术&#xff08;移动/联通/电信自动择优&#xff09;有效解决单一运营商信号覆盖盲区问题&…...

17.10 LangSmith Evaluation 深度实战:构建智能评估体系驱动大模型进化

LangSmith Evaluation 深度实战:构建智能评估体系驱动大模型进化 关键词:LangSmith 评估体系, 大模型质量评估, 自动化评测流水线, 多维度指标分析, 生产环境模型监控 1. 评估体系设计哲学 LangSmith Evaluation 采用 规则评估+模型评估+人工反馈 三位一体的评估框架: #me…...

Gravitino SparkConnector 实现原理

Gravitino SparkConnector 实现原理 本文参考了官网介绍&#xff0c;想看官方解析请参考 官网地址 本文仅仅介绍原理 文章目录 Gravitino SparkConnector 实现原理背景知识-Spark Plugin 介绍(1) **插件加载**(2) **DriverPlugin 初始化**(3) **ExecutorPlugin 初始化**(4) *…...

前端开发好用的AI工具介绍

以下是前端开发中提升效率的 AI 工具 推荐&#xff0c;涵盖代码生成、UI设计、调试优化等场景&#xff1a; 一、代码生成与辅助工具 工具名称特点适用场景GitHub Copilot基于 OpenAI&#xff0c;智能代码补全&#xff08;支持 JS/TS/React/Vue&#xff09;快速生成代码片段、函…...

Linux的用户与权限--第二天

认知root用户&#xff08;超级管理员&#xff09; root用户用于最大的系统操作权限 普通用户的权限&#xff0c;一般在HOME目录内部不受限制 su与exit命令 su命令&#xff1a; su [-] 用户名 -符号是可选的&#xff0c;表示切换用户后加载环境变量 参数为用户名&#xff0c…...

COUNT(CASE WHEN ... THEN ... END)详解

在 SQL 查询中&#xff0c;COUNT(CASE WHEN ... THEN ... END) 是一种常见的用法&#xff0c;用于统计满足特定条件的记录数。具体例子&#xff1a; # sexType 2表示女生 COUNT(CASE WHEN h_employee.sexType 2 THEN 1 END) AS 女员工人数解释 CASE WHEN ... THEN ... END&a…...

音视频入门基础:RTP专题(14)——FFmpeg源码中,对H.264的各种RTP有效载荷结构的解析

一、引言 由《音视频入门基础&#xff1a;RTP专题&#xff08;10&#xff09;——FFmpeg源码中&#xff0c;解析RTP header的实现》可以知道&#xff0c;FFmpeg源码的rtp_parse_packet_internal函数的前半部分实现了解析某个RTP packet的RTP header的功能。而在解析完RTP head…...

FPGA——4位全加器及3-8译码器的实现

文章目录 一、全加器1、Verilog实现四位全加器2、下载测试 二、3-8译码器1、Verilog实现3-8译码器2、7段数码管显示3-8译码器 三、总结四、参考资料 一、全加器 全加器的定义&#xff1a; 全加器英语名称为full-adder&#xff0c;是用门电路实现两个二进制数相加并求出和的组合…...

软考中级-数据库-3.4 数据结构-图

图的定义 一个图G(Graph)是由两个集合:V和E所组成的&#xff0c;V是有限的非空顶点(Vertex)集合&#xff0c;E是用顶点表示的边(Edge)集合&#xff0c;图G的顶点集和边集分别记为V(G)和E(G)&#xff0c;而将图G记作G(V&#xff0c;E)。可以看出&#xff0c;一个顶点集合与连接这…...

软考中级-数据库-3.3 数据结构-树

定义:树是n(n>=0)个结点的有限集合。当n=0时称为空树。在任一非空树中,有且仅有一个称为根的结点:其余结点可分为m(m>=0)个互不相交的有限集T1,T2,T3...,Tm…,其中每个集合又都是一棵树,并且称为根结点的子树。 树的相关概念 1、双亲、孩子和兄弟: 2、结点的度:一个结…...

Win11被背刺,官方泄露免费激活方法

AI已经成为科技圈的主旋律了&#xff0c;在PC圈的龙头微软也不例外。 但最近喜欢背刺用户、极力推崇AI的微软被自家产品背刺了一把。 罪魁祸首就是Microsoft Copilot&#xff0c;如果向Microsoft Copilot提问&#xff0c;是否可以帮忙提供激活Windows11的脚本。 Copilot会立马…...

第十天-字符串:编程世界的文本基石

在编程的广阔领域中&#xff0c;字符串是极为重要的数据类型&#xff0c;它就像一座桥梁&#xff0c;连接着人类的自然语言和计算机能够理解与处理的数字信息。下面&#xff0c;让我们深入探索字符串的世界。 一、字符串简介 字符串是由零个或多个字符组成的有序序列&#xff…...

CentOS7 安装Redis 6.2.6 详细教程

本文主要介绍CentOS7系统下安装Redis6.2.6的详细教程。 1.安装依赖 redis是基于C语言开发&#xff0c;因此想要在服务器上运行redis需要验证是否安装了gcc&#xff0c;没有安装gcc则需先安装 查看是否安装gcc gcc -v如果没有安装gcc&#xff0c;则通过如下命令安装 yum in…...

VsCode使用

vscode前端vue项目启动&#xff1a;Vue项目的创建启动及注意事项-CSDN博客 vscode使用教程&#xff1a;史上最全vscode配置使用教程 - 夏天的思考 - 博客园 vscode如何从git拉取代码&#xff1a;vscode如何从git拉取代码 • Worktile社区...

mac上最好的Python开发环境之Anaconda+Pycharm

文章目录 一、前言 1. Anaconda介绍2. Pycharm介绍 编码协助项目代码导航代码分析Python重构支持Django框架集成版本控制 二、下载Anaconda和Pycharm 1. 下载Anaconda2. 下载Pycharm 三、安装Anaconda和Pycharm 1. 安装Anaconda2. 安装Pycharm 一、前言 1. Anaconda介绍 …...

防火墙旁挂组网双机热备负载均衡

一&#xff0c;二层交换网络&#xff1a; 使用MSTPVRRP组网形式 VLAN 2--->SW3为主,SW4 作为备份 VLAN 3--->SW4为主,SW3 作为备份 MSTP 设计 --->SW3 、 4 、 5 运行 实例 1 &#xff1a; VLAN 2 实例 2 &#xff1a; VLAN 3 SW3 是实例 1 的主根&#xff0c;实…...

Docker 学习(三)——数据管理

容器中的管理数据主要有两种方式&#xff1a; 数据卷 &#xff08;Data Volumes&#xff09;&#xff1a; 容器内数据直接映射到本地主机环境&#xff1b; 数据 卷容器&#xff08; Data Volume Containers&#xff09;&#xff1a; 使用特定容器维护数据卷 1.数据卷 数据卷…...

中间件专栏之MySQL篇——MySQL缓存策略

本文所说的MySQL缓存策略与前文提到的buffer pool不同&#xff0c;那是MySQL内部自己实现的&#xff0c;本问所讲的缓存策略是使用另一个中间件redis来缓存MySQL中的热点数据。 一、为什么需要MySQL缓存方案 缓存用户定义的热点数据&#xff0c;用户可以直接从缓存中获取热点…...

高频 SQL 50 题(基础版)_196. 删除重复的电子邮箱

高频 SQL 50 题&#xff08;基础版&#xff09;_196. 删除重复的电子邮箱 思路 思路 DELETE p1 FROM Person p1,Person p2 WHEREp1.Email p2.Email AND p1.Id > p2.Id...

github进不去,一直显示错误

1、进入网址Dns检测|Dns查询 - 站长工具 2、复制检测出来的任意一个ip 3、打开电脑的文件夹&#xff1a;C:\Windows\System32\drivers\etc 下的hosts文件下复制这个ip地址 20.205.243.166 4、winr 打开cmd&#xff0c;输入ipconfig/flushdns ipconfig/flushdns出现这个就可以…...

MWC 2025|美格智能发布基于高通®X85 5G调制解调器及射频的新一代5G-A通信模组SRM819W

3月3日&#xff0c;在MWC 2025世界移动通信大会上&#xff0c;美格智能正式推出基于高通X85调制解调器及射频的新一代5G-A通信模组SRM819W&#xff0c;集5G-A、毫米波、AI加持的网络优化等最前沿的通信技术&#xff0c;成为行业首批搭载高通X85的5G通信模组产品&#xff0c;将助…...

【零基础到精通Java合集】第十集:List集合框架

课程标题:List集合框架(15分钟) 目标:掌握List接口核心实现类(ArrayList/LinkedList)的使用与场景选择,熟练操作有序集合 0-1分钟:List概念引入 以“购物清单”类比List特性:元素有序(添加顺序)、可重复、支持索引访问。说明List是Java集合框架中最常用的数据结构…...

《今日-AI-编程-人工智能日报》

一、AI行业动态 荣耀发布“荣耀阿尔法战略” 荣耀在“2025世界移动通信大会”上宣布&#xff0c;将从智能手机制造商转型为全球领先的AI终端生态公司&#xff0c;并计划未来五年投入100亿美元建设AI设备生态。荣耀展示了基于GUI的个人移动AI智能体&#xff0c;并推出多款AI终端…...

在 MyBatis 中,若数据库字段名与 SQL 保留字冲突解决办法

在 MyBatis 中&#xff0c;若数据库字段名与 SQL 保留字冲突&#xff0c;可通过以下方法解决&#xff1a; 目录 一、使用转义符号包裹字段名二、通过别名映射三、借助 MyBatis-Plus 注解四、全局配置策略&#xff08;辅助方案&#xff09;最佳实践与注意事项 一、使用转义符号…...

从基础到实践(十):MOS管的全面解析与实际应用

MOS管&#xff08;金属-氧化物半导体场效应晶体管&#xff09;是现代电子技术的基石&#xff0c;凭借高输入阻抗、低功耗和易集成特性&#xff0c;成为数字电路、电源管理和信号处理的核心元件。从微处理器到新能源汽车电驱系统&#xff0c;其高效开关与放大功能支撑了计算机、…...

电源测试系统有哪些可以利用AI工具的科技??

AI技术的发展对电源模块测试系统的影响是深远的&#xff0c;不仅协助系统提升了测试效率和精度&#xff0c;还推动了测试方法的创新和智能化。那么在电源测试系统中哪些模块可以利用AI工具实现自动化测试? 1. 自动化测试与效率提升 智能测试流程优化 AI算法可以自动优化测试…...

RabbitMQ 最新版:安装、配置 与Java 接入详细教程

目录 一、RabbitMQ 简介二、RabbitMQ 的安装1. 安装 Erlang下载 Erlang安装 Erlang2. 安装 RabbitMQ下载 RabbitMQ安装 RabbitMQ3. 配置环境变量4. 启用管理插件三、RabbitMQ 的配置1. 创建用户和设置权限2. 配置文件四、Java 接入 RabbitMQ1. 添加依赖2. 创建连接3. 创建通道4…...

股市现期驱动因子

在股票投资中&#xff0c;我们把驱动股市收益的基本元素称为基本因素&#xff1a; 例如资产负债、现金流量 从短期来看&#xff0c;股市的上涨和下跌基于市场情绪&#xff0c;它更依赖于投资者的期望&#xff0c;投它涨的人多&#xff0c;它就涨。从长期来看&#xff0c;股市…...

物联网中的气象监测设备具备顶级功能

物联网中的气象监测设备具备顶级功能时&#xff0c;通常集成GPS、数据上报和预警系统&#xff0c;以确保精准监测和及时响应。以下是这些功能的详细说明&#xff1a; 1. GPS定位 精准定位&#xff1a;GPS模块提供设备的精确地理位置&#xff0c;确保数据与具体位置关联&#…...

算法1-4 凌乱的yyy / 线段覆盖

题目描述 现在各大 oj 上有 n 个比赛&#xff0c;每个比赛的开始、结束的时间点是知道的。 yyy 认为&#xff0c;参加越多的比赛&#xff0c;noip 就能考的越好&#xff08;假的&#xff09;。 所以&#xff0c;他想知道他最多能参加几个比赛。 由于 yyy 是蒟蒻&#xff0c…...

gn学习存档

以下答案均由deepseek提供&#xff0c;仅作学习存档。 1. 举例说明action和action_foreach区别 场景设定 假设需要处理一组文件&#xff1a; 输入文件&#xff1a;src/data/file1.txt, src/data/file2.txt, src/data/file3.txt处理逻辑&#xff1a;将每个 .txt 文件转换为 …...

SQL注入练习场:PHPStudy+SQLI-LABS靶场搭建教程(零基础友好版)

注意&#xff1a;文中涉及演示均为模拟测试&#xff0c;切勿用于真实环境&#xff0c;任何未授权测试都是违法行为&#xff01; 一、环境准备 下载PHPStudy 官网下载地址&#xff1a;https://www.xp.cn/php-study&#xff08;选择Windows版&#xff09; 安装时建议选择自定…...