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

区块链-P2P(八)

前言
P2P网络(Peer-to-Peer Network)是一种点对点的网络结构,它没有中心化的服务器或者管理者,所有节点都是平等的。在P2P网络中,每个节点都可以既是客户端也是服务端,这种网络结构的优点是去中心化、可扩展性强、抗攻击性强等。

1:P2P网络的优点

区块链 P2P 网络的优点有:

去中心化:没有中心化的服务器或者管理者,所有节点都是平等的。
高可用性:由于没有单点故障,所以整个系统非常稳定。
高安全性:由于每个节点都有完整的数据副本,所以即使有部分节点被攻击或者宕机,整个系统依然可以正常运行。
高效性:由于数据可以在多个节点之间共享和传输,所以整个系统非常高效。

2:分类
根据具体应用不同,可以把P2P分为以下这些类型[1]:
·提供文件和其它内容共享的P2P网络,例如Napster、Gnutella、eDonkey、emule、BitTorrent等;
·挖掘P2P对等计算能力和存储共享能力,例如SETI@home 、Avaki、Popular Power等;
·基于P2P方式的协同处理与服务共享平台,例如JXTA、Magi、Groove、.NET My Service等;
·即时通讯交流,包括ICQ、OICQ、Yahoo Messenger等;
·安全的P2P通讯与信息共享,例如Skype、Crowds、Onion Routing等。

3:区块链中的P2P网络
作为区块链的底层传输方式,P2P 技术帮助区块链成功实现了点对点的传播。比特币、以太坊等众多区块链项目都实现了属于自己的P2P网络协议,根据区块链的运行特点,我们可以总结出区块链客户端节点所组成p2p网络的一些需求:
1.节点可以任意地加入和离开网络;
2.每个节点所存储的数据(区块),在理想状态下是一致的(当然光凭p2p网络不能达到数据一致性,它只是提供了数据传输的逻辑通道,我们还需要共识算法来配合实现数据一致性);
3.在区块链网络中,查找数据时不需要向整个网络广播发送请求,正常情况下任意一个(或相邻几个)节点就可以提供完整的区块数据。

4:直接上代码
P2P打洞
UDP 打洞更容易点,网上一堆,不发了

TCP SERVER

#include <stdio.h>  #include <signal.h>  #include <fcntl.h>  
#include <stdlib.h>  
#include <errno.h>  
#include <string.h>  #ifdef _WIN32
#include <WinSock2.h>
#include<Ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <unistd.h>  
#include <sys/socket.h> 
#include <arpa/inet.h>  
#endif#define MAXLINE 128  
#define SERV_PORT 7119 //发生了致命错误,退出程序  
void error_quit(const char *str)
{fprintf(stderr, "%s", str);//如果设置了错误号,就输入出错原因  
#ifdef _WIN32if (errno != 0) {const int errmsglen = 255;char errmsg[errmsglen];strerror_s(errmsg, errmsglen, errno);fprintf(stderr, " : %s", errmsg);}
#elseif (errno != 0)fprintf(stderr, " : %s", strerror(errno));
#endifprintf("\n");exit(1);
}int main(void)
{int i, res, cur_port;
#ifdef _WIN32SOCKET  connfd, firstfd, listenfd;WSADATA wsaData;WORD  wVersionRequested = MAKEWORD(2, 2);WSAStartup(wVersionRequested, &wsaData);
#elseint connfd, firstfd, listenfd;
#endifint count = 0;char str_ip[MAXLINE];    //缓存IP地址  char cur_inf[MAXLINE];   //当前的连接信息[IP+port]  char first_inf[MAXLINE];    //第一个链接的信息[IP+port]  char buffer[MAXLINE];    //临时发送缓冲区  socklen_t clilen;struct sockaddr_in cliaddr;struct sockaddr_in servaddr;//创建用于监听TCP协议套接字          listenfd = socket(AF_INET, SOCK_STREAM, 0);memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);//把socket和socket地址结构联系起来         res = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));if (-1 == res)error_quit("bind error");//开始监听端口         res = listen(listenfd, INADDR_ANY);if (-1 == res)error_quit("listen error");while (1){//接收来自客户端的连接  connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);if (-1 == connfd)error_quit("accept error");inet_ntop(AF_INET, (void*)&cliaddr.sin_addr, str_ip, sizeof(str_ip));count++;//对于第一个链接,将其的IP+port存储到first_inf中,  //并和它建立长链接,然后向它发送字符串'first',  if (count == 1){firstfd = connfd;cur_port = ntohs(cliaddr.sin_port);snprintf(first_inf, MAXLINE, "%s %d", str_ip, cur_port);#ifdef _WIN32strcpy_s(cur_inf, MAXLINE, "first\n");send(connfd, cur_inf, strlen(cur_inf) + 1, 0);
#elsestrcpy(cur_inf, "first\n");write(connfd, cur_inf, strlen(cur_inf) + 1);
#endif}//对于第二个链接,将其的IP+port发送给第一个链接,  //将第一个链接的信息和他自身的port返回给它自己,  //然后断开两个链接,并重置计数器  else if (count == 2){cur_port = ntohs(cliaddr.sin_port);snprintf(cur_inf, MAXLINE, "%s %d\n", str_ip, cur_port);snprintf(buffer, MAXLINE, "%s %d\n", first_inf, cur_port);#ifdef _WIN32send(connfd, buffer, strlen(buffer) + 1,0);send(firstfd, cur_inf, strlen(cur_inf) + 1,0);closesocket(connfd);closesocket(firstfd);
#elsewrite(connfd, buffer, strlen(buffer) + 1);write(firstfd, cur_inf, strlen(cur_inf) + 1);close(connfd);close(firstfd);
#endifcount = 0;}//如果程序运行到这里,那肯定是出错了  elseerror_quit("Bad required");}
#ifdef _WIN32WSACleanup();
#endifreturn 0;
}
/*
运行示例:
(第一个终端)
ubuntu@ubuntu ~/program/tcode $ gcc server.c -o server
ubuntu@ubuntu ~/program/tcode $ ./server &
[1] 4688
ubuntu@ubuntu ~/program/tcode $ gcc client.c -o client
ubuntu@ubuntu ~/program/tcode $ ./client localhost
Get: first
ff: 127.0.0.1 38052
send message: Hello, world
send message: Hello, world
send message: Hello, world
.................第二个终端:
ubuntu@ubuntu ~/program/tcode $ ./client localhost
Get: 127.0.0.1 38073 38074
connect error
recv message: Hello, world
recv message: Hello, world
recv message: Hello, world
*/

client

#include <stdio.h>  #include <signal.h>  #include <fcntl.h>  
#include <stdlib.h>  
#include <errno.h>  
#include <string.h>  #ifdef _WIN32
#include <WinSock2.h>
#include<Ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <unistd.h>  
#include <sys/socket.h> 
#include <arpa/inet.h>  
#endif#define MAXLINE 128  
#define SERV_PORT 7119 typedef struct
{char ip[32];int port;
}server;void error_quit(const char *str)
{fprintf(stderr, "%s", str);//如果设置了错误号,就输入出错原因  
#ifdef _WIN32if (errno != 0) {const int errmsglen = 255;char errmsg[errmsglen];strerror_s(errmsg, errmsglen, errno);fprintf(stderr, " : %s", errmsg);}
#elseif (errno != 0)fprintf(stderr, " : %s", strerror(errno));
#endifprintf("\n");exit(1);
}int main(int argc, char **argv)
{int i, res, port;
#ifdef _WIN32SOCKET  connfd, sockfd, listenfd;WSADATA wsaData;WORD  wVersionRequested = MAKEWORD(2, 2);WSAStartup(wVersionRequested, &wsaData);BOOL bReuseaddr = TRUE;
#elseint connfd, sockfd, listenfd;unsigned int value = 1;
#endifchar buffer[MAXLINE];socklen_t clilen;struct sockaddr_in servaddr, sockaddr, connaddr;server other;if (argc != 2)error_quit("Using: ./client <IP Address>");//创建用于链接(主服务器)的套接字          sockfd = socket(AF_INET, SOCK_STREAM, 0);memset(&sockaddr, 0, sizeof(sockaddr));sockaddr.sin_family = AF_INET;sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);sockaddr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &sockaddr.sin_addr);//设置端口可以被重用  
#ifdef _WIN32setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(BOOL));
#elsesetsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
#endif//连接主服务器  res = connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));if (res < 0)error_quit("connect error");//从主服务器中读取出信息  
#ifdef _WIN32res = recv(sockfd, buffer, MAXLINE,0);
#elseres = read(sockfd, buffer, MAXLINE);
#endifif (res < 0)error_quit("read error");printf("Get: %s", buffer);//若服务器返回的是first,则证明是第一个客户端  if ('f' == buffer[0]){//从服务器中读取第二个客户端的IP+port  
#ifdef _WIN32res = recv(sockfd, buffer, MAXLINE, 0);sscanf_s(buffer, "%s %d", other.ip,&other.port);
#elseres = read(sockfd, buffer, MAXLINE);sscanf(buffer, "%s %d", other.ip, &other.port);
#endifprintf("ff: %s %d\n", other.ip, other.port);//创建用于的套接字          connfd = socket(AF_INET, SOCK_STREAM, 0);memset(&connaddr, 0, sizeof(connaddr));connaddr.sin_family = AF_INET;connaddr.sin_addr.s_addr = htonl(INADDR_ANY);connaddr.sin_port = htons(other.port);inet_pton(AF_INET, other.ip, &connaddr.sin_addr);//尝试去连接第二个客户端,前几次可能会失败,因为穿透还没成功,  //如果连接10次都失败,就证明穿透失败了(可能是硬件不支持)  while (1){static int j = 1;res = connect(connfd, (struct sockaddr *)&connaddr, sizeof(connaddr));if (res == -1){if (j >= 10)error_quit("can't connect to the other client\n");printf("connect error, try again. %d\n", j++);
#ifdef _WIN32Sleep(1);
#elsesleep(1);
#endif}elsebreak;}
#ifdef _WIN32strcpy_s(buffer, MAXLINE, "Hello, world\n");
#elsestrcpy(buffer, "Hello, world\n");
#endif//连接成功后,每隔一秒钟向对方(客户端2)发送一句hello, world  while (1){
#ifdef _WIN32res = send(connfd, buffer, strlen(buffer) + 1,0);
#elseres = write(connfd, buffer, strlen(buffer) + 1);
#endifif (res <= 0)error_quit("write error");printf("send message: %s", buffer);
#ifdef _WIN32Sleep(1);
#elsesleep(1);
#endif}}//第二个客户端的行为  else{//从主服务器返回的信息中取出客户端1的IP+port和自己公网映射后的port  
#ifdef _WIN32sscanf_s(buffer, "%s %d %d", other.ip, &other.port, &port);
#elsesscanf(buffer, "%s %d %d", other.ip, &other.port, &port);
#endif//创建用于TCP协议的套接字          sockfd = socket(AF_INET, SOCK_STREAM, 0);memset(&connaddr, 0, sizeof(connaddr));connaddr.sin_family = AF_INET;connaddr.sin_addr.s_addr = htonl(INADDR_ANY);connaddr.sin_port = htons(other.port);inet_pton(AF_INET, other.ip, &connaddr.sin_addr);//设置端口重用  
#ifdef _WIN32BOOL bReuseaddr = TRUE;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(BOOL));
#elsesetsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
#endif//尝试连接客户端1,肯定会失败,但它会在路由器上留下记录,  //以帮忙客户端1成功穿透,连接上自己   res = connect(sockfd, (struct sockaddr *)&connaddr, sizeof(connaddr));if (res < 0)printf("connect error\n");//创建用于监听的套接字          listenfd = socket(AF_INET, SOCK_STREAM, 0);memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(port);//设置端口重用  
#ifdef _WIN32setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(BOOL));
#elsesetsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
#endif//把socket和socket地址结构联系起来   res = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));if (-1 == res)error_quit("bind error");//开始监听端口         res = listen(listenfd, INADDR_ANY);if (-1 == res)error_quit("listen error");while (1){//接收来自客户端1的连接  connfd = accept(listenfd, (struct sockaddr *)&sockaddr, &clilen);if (-1 == connfd)error_quit("accept error");while (1){//循环读取来自于客户端1的信息  
#ifdef _WIN32res = recv(connfd, buffer, MAXLINE,0);
#elseres = read(connfd, buffer, MAXLINE);
#endifif (res <= 0)error_quit("read error");printf("recv message: %s", buffer);}
#ifdef _WIN32closesocket(connfd);
#elseclose(connfd);
#endif}}return 0;
}

golang的参考 github.com/ethereum/go-ethereum/
在这里插入图片描述
在这里插入图片描述

参考 https://blog.csdn.net/muxuen/article/details/137231514
在这里插入图片描述

5:运行结果(暂时手上没有公网服务器,请自行编译测试)

如果觉得有用,麻烦点个赞,加个收藏

相关文章:

区块链-P2P(八)

前言 P2P网络&#xff08;Peer-to-Peer Network&#xff09;是一种点对点的网络结构&#xff0c;它没有中心化的服务器或者管理者&#xff0c;所有节点都是平等的。在P2P网络中&#xff0c;每个节点都可以既是客户端也是服务端&#xff0c;这种网络结构的优点是去中心化、可扩展…...

数据库管理的利器Navicat —— 全面测评与热门产品推荐

在数据库管理领域&#xff0c;Navicat无疑是一款深受欢迎的软件。作为一个强大的数据库管理和开发工具&#xff0c;它支持多种数据库类型&#xff0c;包括MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL等。本文将全面测评Navicat的核心功能&#xff0c;同时推荐几款…...

如何让Google收录我的网站?

其实仅仅只是收录&#xff0c;只要在GSC提交网址&#xff0c;等个两三天&#xff0c;一般就能收录&#xff0c;但收录是否会掉&#xff0c;这篇内容收录了是否有展现&#xff0c;排名&#xff0c;就是另外一个课题了&#xff0c;如果不收录&#xff0c;除了说明你的网站有问题&…...

03 Flask-添加配置信息

回顾之前学习的内容 02 Flask-快速上手 Flask 中最简单的web应用组成 1. 导入核心库 Flask from flask import Flask2. 实例化 web应用 注意&#xff1a;不要漏了 app Flask(__name__) 中的 __name__ 表示&#xff1a;是从当前的py文件实例化 app Flask(__name__)3. 创…...

Codes 开源研发项目管理平台——敏捷测试管理创新解决方案

前言 Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台&#xff0c;支持云端认证、本地部署、全部功能开放&#xff0c;并且对30人以下团队免费。它通过整合迭代、看板、度量和自动化等功能&#xff0c;简化测试协同工作&#xff0c;使敏捷测试更易于实施。并提供低成本的…...

耗时一个月,我做了一个网页视频编辑器

最近又肝了一个多月&#xff0c;终于把这个网页视频编辑器做好了&#xff0c;下面我来简单介绍一下如何使用 注意目前该功能还处在测试阶段&#xff0c;可能会有很多问题&#xff0c;后续我会不断修复 体验地址 app.zyjj.cc 界面介绍 整个剪辑界面包括4个区&#xff0c;左边是…...

uniapp 做一个查看图片的组件,图片可缩放移动

因为是手机端&#xff0c;所以需要触摸可移动&#xff0c;双指放大缩小。 首先在components里建个组件 查看图片使用 uni-popup 弹窗 要注意 transform的translate和scale属性在同一标签上不会一起生效 移动就根据触摸效果进行偏移图片 缩放就根据双指距离的变大变小进行缩…...

卡车配置一键启动无钥匙进入手机控车

‌ 卡车智能一键启动无钥匙进入手机控车&#xff0c;通过手机应用程序与汽车内置硬件、软件的无线通信&#xff0c;实现对汽车的远程控制‌。 卡车改装一键启动的步骤包括安装门把手的感应装置、拆卸仪表台和门板&#xff0c;取出内部的待接线束&#xff0c;并将一键启动…...

计算机网络基础概念 交换机、路由器、网关、TBOX

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、VLAN是什么&#xff1f;二 、交换机三、路由器四、网关五、TBOX六、问题1 、网关和交换机的区别2、网关和路由器的区别 总结 前言 工作有感而发&#xff0…...

labview禁用8080端口

需求背景 最近电脑上安装了labview全家桶,发现idea的8080端口项目启动报错,一直提示8080端口被占用。最简单的办法就是找到8080端口的服务,然后关闭这个服务。但是我不想这么做,我想把labview的web服务器的端口给修改了。 操作教程 1、cmd查看8080端口 2、windows进程 同…...

字符串的KMP算法详解及C/C++代码实现

1. 原由 紧接上文&#xff0c;我们知道了暴力匹配的算法在时间运行上的缺陷&#xff0c;假设字符串T的长度为n&#xff0c;字符串P的长度为m&#xff0c;则整个算法的时间复杂度为O( n * m )&#xff0c;而对于一个复杂的现实情况而言 n >> m >> 2 &#xff08;即…...

2024年数学建模比赛题目及解题代码

目录 一、引言 1. 1竞赛背景介绍 1.1.1数学建模竞赛概述 1.1.2生产过程决策问题在竞赛中的重要性 1.2 解题前准备 1.2.2 工具与资源准备 1.2.3 心态调整与策略规划 二、问题理解与分析 三、模型构建与求解 3.1 模型选择与设计 3.1.1 根据问题特性选择合适的数学模型类…...

BERT 论文逐段精读【论文精读】

BERT: 近 3 年 NLP 最火 CV: 大数据集上的训练好的 NN 模型&#xff0c;提升 CV 任务的性能 —— ImageNet 的 CNN 模型 NLP: BERT 简化了 NLP 任务的训练&#xff0c;提升了 NLP 任务的性能 BERT 如何站在巨人的肩膀上的&#xff1f;使用了哪些 NLP 已有的技术和思想&#xff…...

在Flask中实现跨域请求(CORS)

在Flask中实现跨域请求&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;主要涉及到对Flask应用的配置&#xff0c;以允许来自不同源的请求访问服务器上的资源。以下是在Flask中实现CORS的详细步骤和方法&#xff1a; 一、理解CORS CORS是一种机制&…...

在桌面商业分析应用程序中启用高级 Web UI

挑战 Mercur Business Control 应用程序在企业界&#xff0c;尤其是金融领域&#xff0c;拥有悠久的应用历史。它帮助企业处理、可视化和分析海量数据&#xff0c;从而做出明智的商业决策。 随着产品的不断演进和现代化&#xff0c;Mercur Solutions AB 为该应用创建了 Web 客…...

CentOS Stream 8 通过 Packstack 安装开源 OpenStack(V版)

1、环境规划以及网卡配置 controller IP&#xff1a;192.168.235.101 compute IP&#xff1a;192.168.235.102 控制节点 [rootluck ~]# cd /etc/sysconfig/network-scripts/ [rootluck network-scripts]# vi ifcfg-ens160 [rootluck network-scripts]# cat ifcfg-ens160 TYP…...

OpenSSL工具验证RSA证书

openssl x509 是一个用于处理 X.509 证书的命令行工具。常用的 openssl x509 命令&#xff1a; -in <file>&#xff1a;指定输入文件。-out <file>&#xff1a;指定输出文件。-noout&#xff1a;不输出证书信息。-text&#xff1a;以文本格式输出证书信息。-pubke…...

架构师白话分布式系统

对于分布式系统的定义,大致可以理解为如下的两个点 分布式系统从整体的体量来说,它内部是由很多的服务器、服务实例组成。所提供的用户服务是由一组相互独立运行的服务器来提供。对于用户来说,这个多服务器的系统就跟一个服务器一样,感觉不到每个单独的服务器实例的存在。从…...

C++ 中 vector 的常用功能介绍

在 C 中&#xff0c;vector 是一种常用的动态数组容器&#xff0c;提供了方便的自动扩展、内存管理以及各种便捷的操作方法。它是 C 标准模板库&#xff08;STL&#xff09;的一部分&#xff0c;适用于需要动态存储和管理大量元素的场景。 在本文中&#xff0c;我们将简要介绍…...

[QT] QT事件与事件重写

一.事件 事件(event)是由系统或者 Qt本身在不同的场景下发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口关闭等都会发出一个相应的事件。 一些事件在用户操作时发出(如鼠标/键盘事件); 另一些事件则是由系统自动发出(如计时器事件)。 Qt窗口中对于产生的一系列事件都…...

c# 视觉识别图片文字 二维码

1.二维码识别 插件 ZXing.Net using System; using System.Drawing; // 如果你使用的是System.Drawing.Common using ZXing;class Program {static void Main(){string imagePath "path_to_your_qr_code_image.png";var barcodeBitmap (Bitmap)Image.FromFile(im…...

UEFI——访问PCI/PCIE设备(二)

一、支持访问PCI/PCIE设备的Protocol UEFI中提供了两个主要的模块来支持PCI总线&#xff0c;一是PCI Host Bridge&#xff08;PCI主桥&#xff09;控制器驱动&#xff0c;另一个是PCI总线驱动。这两个模块是和特定的平台硬件绑定的&#xff0c;在这种机制下&#xff0c;屏蔽了…...

决策树算法的介绍与应用

目录 引言 决策树算法的基本原理 表格总结&#xff1a;决策树的构建步骤 决策树算法的 MATLAB 实现 示例&#xff1a;使用决策树进行分类预测 决策树的应用场景 表格总结&#xff1a;决策树的主要应用领域 决策树的优势与局限 结论 引言 决策树是一种广泛应用于数据挖掘…...

杰发科技Bootloader(3)—— 基于7801的APP切到Boot

为了方便在APP中跳转到Boot重新进行升级&#xff0c;有两种办法&#xff0c;7840同样可以使用。 1. 调用reset接口进行复位&#xff0c;复位后会先进Boot&#xff0c;再自动跳转到App。 NVIC_SystemReset(); 2. 直接使用跳转指令&#xff0c;参考Boot跳转到App代码&#xff0…...

Leetcode面试经典150题-138.随机链表的复制

题目比较简单&#xff0c;重点是理解思想&#xff0c;random不管&#xff0c;copy一定要放在next 而且里面的遍历过程不能省略 解法都在代码里&#xff0c;不懂就留言或者私信 /* // Definition for a Node. class Node {int val;Node next;Node random;public Node(int val…...

freemarker模板学习笔记

文章目录 freemarker常用指令if-elseif-else指令switch, case, default, break指令list, else, items, sep, break 指令<#list>指令语法<#else> 指令<#items> 指令<#sep> 指令<#break> 指令 include 指令<#include> 基础知识<#include&…...

高亚科技与广东海悟携手,打造全流程电子竞标管理平台!

近日&#xff0c;中国企业管理软件资深服务商高亚科技与广东海悟科技有限公司&#xff08;以下简称“海悟”&#xff09;正式签署合作协议&#xff0c;双方将基于高亚科技的8Manage SRM系统&#xff0c;推进海悟采购管理的数字化升级&#xff0c;实现全流程在线电子竞标管理&am…...

240908-结合DBGPT与Ollama实现RAG本地知识检索增强

A. 最终效果 B. 背景说明 DBGPT在0.5.6版本中开始支持Ollama&#xff1a;v0.5.6 版本更新 网友对其Web端及界面端的设置进行了分享&#xff1a; feat(model): support ollama as an optional llm & embedding proxy by GITHUBear Pull Request #1475 eosphoros-ai/DB-G…...

AMD ThinkSystem服务器上的 Linux 和 C 状态设置 - Lenovo ThinkSystem

受影响的配置 该系统可以是以下任何Lenovo服务器&#xff1a; ThinkSystem 、SR645&#xff08; ThinkSystem &#xff09;ThinkSystem &#xff0c;SR645 V3&#xff08; ThinkSystem &#xff09;ThinkSystem &#xff0c;SR635 V3&#xff08; ThinkSystem &#xff09;Th…...

Redis过期删除和缓存淘汰

1. 过期删除 在 Redis 中&#xff0c;键的过期删除机制主要包括惰性删除&#xff08;Lazy Deletion&#xff09;和定期删除&#xff08;Periodic Deletion&#xff09;。这两种策略有各自的优缺点&#xff0c;Redis 最终会结合这两种方法来管理过期键。 1.1 惰性删除&#xf…...