32 <字节技术总监推荐的嵌入式、编程、c、底层硬核学习coding笔记#25年3月19日开始更新系列# >超硬核区块链算法仿真:联盟链PBFT多线程仿真实现 :c语言完全详解版 共5篇 第1部分

C语言实现PBFT共识算法模拟

1 22年年底想用gpt做出一个pbft的算法仿真,到了25年终于可以结合gpt grok perplexcity deepseek等实现了!!!!!


调试结果


解释:

这个程序模拟了一个小型区块链网络:

节点:80个节点,其中节点0是主节点(负责发起请求),节点1到79是从节点(负责响应)。
目标:处理100个请求,通过PBFT的三个阶段(Pre-Prepare、Prepare、Commit)达成共识。
通信方式:每个节点有自己的消息队列,主节点和从节点通过队列传递消息,模拟网络通信。
并发性:使用多线程(79个从节点线程+1个主线程),模拟区块链节点的并行工作。
延迟:每个消息传递有0-10ms的随机延迟,模拟真实网络环境。
同步工具:使用互斥锁和条件变量,确保线程安全和消息顺序。
运行过程可以分为五个主要阶段:

初始化阶段:设置节点、队列和线程。
主节点发起请求:发送Pre-Prepare消息,启动共识。
从节点处理消息:接收并回复Prepare和Commit消息。
主节点收集回复:收集足够的消息,完成共识。
统计和清理:输出性能指标,释放资源。



引子
-----------------------------------------------------------------------------------------------------


底下是正文:
 

第一部分:破冰与基石——揭开分布式共识的神秘面纱

嘿,各位C语言老铁们,以及所有对分布式系统、区块链技术充满好奇的朋友们!

我是你们的老朋友,一个常年“折腾”在代码世界里的码农。今天,我要和大家分享一个我“憋”了很久,从2022年年底就开始琢磨,直到2025年才终于在AI(没错,就是你们现在用的GPT、Grok、DeepSeek这些大模型!)的“神助攻”下,得以完美实现的硬核项目——用C语言模拟PBFT(Practical Byzantine Fault Tolerance,实用拜占庭容错)算法

你可能会问:“PBFT?那是个啥?听起来就好高大上!”别急,我保证,读完这系列文章,你不仅能透彻理解PBFT的运行机制,还能亲手写出它的模拟代码,甚至能把它吹嘘给你的朋友,让他们对你刮目相看!

1.1 为什么是PBFT?为什么又是C语言?

在分布式系统的汪洋大海中,共识算法就像是定海神针,确保所有节点对某件事情达成一致。想象一下,如果一个团队里,大家对“今天中午吃什么”都各执己见,那午饭就没法吃了,对吧?分布式系统也是一样,如果各个节点对数据的状态、交易的顺序不能达成一致,那整个系统就乱套了。

而PBFT,就是解决这个问题的“老牌劲旅”之一。它不像比特币的PoW(工作量证明)那样需要消耗大量算力,而是在许可链(或者说,节点身份已知且受控的联盟链)和企业级分布式系统中大放异彩。它的特点是高吞吐、低延迟,而且还能容忍拜占庭错误(简单来说,就是有些节点可能会“使坏”,发送错误信息,甚至伪造信息)。

那为什么我们选择C语言来搞这个项目呢?

  1. 性能与底层: C语言以其卓越的性能和对系统底层的直接操控能力而闻名。用C语言实现,能让我们更深刻地理解PBFT算法在资源管理、并发控制上的细节。

  2. 硬核挑战: 对于刷过牛客、力扣100热题榜的你来说,C语言的多线程、内存管理可能已经驾轻就熟。但将这些知识应用于复杂的分布式算法模拟,无疑是一次更高级的挑战,能让你在嵌入式、操作系统等领域走得更远。

  3. “裸奔”的快感: 没有花哨的框架,没有复杂的库依赖,我们用最纯粹的C语言来构建,就像亲手搭建一个精密的机械装置,那种掌控一切的快感,是其他语言难以比拟的。

  4. 面试加分项: 懂PBFT,会C语言实现,这在分布式、区块链、高性能计算等领域的面试中,绝对是亮眼的加分项!

所以,别犹豫了,跟着我,一起踏上这段充满挑战与乐趣的PBFT C语言模拟之旅吧!

1.2 PBFT算法:初探分布式共识的奥秘

在深入代码之前,我们先来快速“扫盲”一下PBFT算法。别担心,我不会给你堆砌复杂的数学公式,咱们用大白话和生活中的例子来理解它。

1.2.1 什么是分布式共识?

想象一下,你和你的几个朋友(分布式系统中的节点)正在玩一个游戏,需要对某个行动(比如“下一步是向左走还是向右走”)达成一致。但你们之间可能存在网络延迟,甚至有人可能故意捣乱(拜占庭错误)。分布式共识算法的目标就是:在这些复杂甚至恶意的情况下,让所有诚实的参与者对某个提议达成一致,并且一旦达成一致,这个结果就不能再改变。

1.2.2 为什么需要共识?

举个最简单的例子:银行转账。 小明给小红转账100块钱。

  • 如果银行系统是单机的,很简单,数据库里小明的余额减100,小红的余额加100。

  • 但如果银行系统是分布式的,有N台服务器都保存着账本。

    • 服务器A说:“转账成功!”

    • 服务器B说:“转账失败!”

    • 服务器C说:“我没收到这个请求!”

    • ... 这不就乱套了吗?谁的账本才是对的?小明和小红的钱到底有没有变? 共识算法就是来解决这个问题的:确保所有服务器(节点)上的账本(数据状态)最终都保持一致。

1.2.3 PBFT的“三板斧”:Pre-Prepare, Prepare, Commit

PBFT算法的核心流程可以概括为三个主要阶段,就像武侠小说里的“三板斧”,一招一式,环环相扣,最终达成共识。

阶段名称

发送者

接收者

消息内容

目的

Pre-Prepare

主节点

所有副本节点

请求内容、视图编号、序列号、摘要

主节点提议一个请求,并广播给所有副本节点。

Prepare

副本节点

所有节点

请求内容、视图编号、序列号、摘要

副本节点确认收到并同意主节点的提议。

Commit

副本节点

所有节点

请求内容、视图编号、序列号、摘要

副本节点确认已准备好执行请求。

简单来说:

  1. Pre-Prepare(预准备):客户端发出请求后,主节点(Primary)收到请求,它会给这个请求分配一个序列号,然后把请求内容和序列号打包成一个Pre-Prepare消息,广播给所有其他副本节点(Replica)。这就像班长(主节点)收到老师的作业(请求)后,把作业内容和编号告诉所有同学(副本节点)。

  2. Prepare(准备):副本节点收到Pre-Prepare消息后,会验证消息的合法性(比如序列号是否正确、是否重复等)。如果验证通过,它会向所有其他节点(包括主节点自己)广播一个Prepare消息,表示“我收到了这个请求,并且我已经准备好处理它了!”。这就像同学们收到作业后,互相告诉一声:“我收到作业了,准备开始写了!”

  3. Commit(提交):当一个节点(无论是主节点还是副本节点)收到了足够多的(2f+1个,f是允许的拜占庭节点数量)Prepare消息后,它就知道“哦,大多数节点都准备好处理这个请求了!”。这时,它会向所有其他节点广播一个Commit消息,表示“我已经准备好提交并执行这个请求了!”。这就像同学们互相确认:“大家都准备好了,那咱们就一起交作业吧!”

当一个节点收到足够多的Commit消息后,它就认为这个请求已经达成共识,可以安全地执行了。

1.2.4 拜占庭将军问题与PBFT的容错能力

你可能听说过“拜占庭将军问题”——一群将军(节点)要对是否进攻达成一致,但其中可能有叛徒(拜占庭节点),他们可能会传递虚假信息,甚至不按协议行事。

PBFT就是为了解决这个问题而生的。它通过多阶段投票消息认证(虽然我们简化版里没有体现,但在实际PBFT中非常重要),确保即使有少数“叛徒”存在,诚实节点也能达成一致。PBFT能够容忍f个拜占庭节点,只要总节点数nge3f+1。

比如,我们模拟的系统有4个节点(1个主节点,3个副本)。那么n=4。 4ge3f+1Rightarrow3ge3fRightarrowfle1。 这意味着我们的系统可以容忍最多1个拜占庭节点。为了达成共识,我们需要2f+1个诚实节点的同意。当f=1时,2f+1=2times1+1=3。所以,在我们的4节点系统中,理论上需要至少3个节点(包括主节点自己)的确认才能达成共识。但在我们这个简化版里,为了演示方便,我们把阈值设置为2,即主节点收到2个副本的回复就认为达成共识(这在没有拜占庭节点,或者拜占庭节点数量少于f的情况下是可行的)。

1.3 搭建我们的PBFT模拟实验室:C语言与Windows环境

好了,理论知识讲完了,咱们开始动手搭建我们的模拟环境!

1.3.1 环境准备

你需要一个C语言的开发环境。我推荐以下两种:

  1. Visual Studio (推荐):如果你在Windows上,Visual Studio是首选。它集成了编译器、调试器和IDE,对Windows API的支持也最好。

  2. MinGW + VS Code:如果你更喜欢轻量级或者跨平台,可以在Windows上安装MinGW(Minimalist GNU for Windows),它提供了GCC编译器。然后配合VS Code,配置好C/C++扩展,也能愉快地开发。

1.3.2 Windows API初体验:为什么需要windows.h

你可能注意到代码开头有这样一行: #include <windows.h> 这行代码引入了Windows操作系统提供的API(应用程序编程接口)。我们的模拟程序需要用到多线程和线程同步机制,这些功能在Windows上都是通过windows.h中定义的函数和数据结构来实现的。

#define _WIN32_WINNT 0x0600 这行,则是为了确保我们能使用到Windows Vista及更高版本中引入的**条件变量(Condition Variables)**功能。条件变量在多线程编程中非常有用,它允许线程在满足特定条件之前等待,避免了忙等待(busy-waiting),提高了效率。0x0600代表Windows Vista。

1.3.3 多线程编程的基石:CreateThreadHANDLEDWORD WINAPILPVOID

在我们的PBFT模拟中,每个节点都将作为一个独立的线程运行。这样才能模拟它们并行处理消息、互相通信的行为。Windows提供了CreateThread函数来创建新线程。

让我们看看CreateThread的“庐山真面目”:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadA
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值