-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
500 lines (261 loc) · 201 KB
/
atom.xml
File metadata and controls
500 lines (261 loc) · 201 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>欢迎来到小面包的小站🥝</title>
<link href="https://eatbreads.github.io/atom.xml" rel="self"/>
<link href="https://eatbreads.github.io/"/>
<updated>2025-06-04T15:45:34.974Z</updated>
<id>https://eatbreads.github.io/</id>
<author>
<name>小面包🥝</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>记录一下本人儿童节当天的阴暗爬行</title>
<link href="https://eatbreads.github.io/posts/5561b902.html"/>
<id>https://eatbreads.github.io/posts/5561b902.html</id>
<published>2025-06-01T16:15:20.000Z</published>
<updated>2025-06-04T15:45:34.974Z</updated>
<content type="html"><![CDATA[<h1>记录一下本人儿童节当天的阴暗爬行</h1><h2 id="前言">前言</h2><p>端午节放假之后,有五个面试,一个字节,一个腾讯,一个快手,一个北京做数据库(感觉挺好的),还有一个上海游戏小厂</p><p>本人之前基本没怎么写过算法,所以有时候面试都很艰难的写出来,于是今天痛定思痛, 怒刷15道力扣</p><p>已经晕厥<br><img src="https://cdn-a.markji.com/files/683c7d921a5e20b2c6aa8519_hd.png?e=1748797362718&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:Fqp8Cp4O9aPaEsuW4nR78jHBE5M=" alt="图片1"></p>]]></content>
<summary type="html"><h1>记录一下本人儿童节当天的阴暗爬行</h1>
<h2 id="前言">前言</h2>
<p>端午节放假之后,有五个面试,一个字节,一个腾讯,一个快手,一个北京做数据库(感觉挺好的),还有一个上海游戏小厂</p>
<p>本人之前基本没怎么写过算法,所以有时候面试都很艰难的写出</summary>
</entry>
<entry>
<title>关于分布式算法和一些分布式架构设计理解</title>
<link href="https://eatbreads.github.io/posts/78dda7e2.html"/>
<id>https://eatbreads.github.io/posts/78dda7e2.html</id>
<published>2025-05-31T15:56:58.000Z</published>
<updated>2025-06-01T02:29:09.299Z</updated>
<content type="html"><![CDATA[<h1 id="关于分布式算法和一些分布式架构设计理解"><a href="#关于分布式算法和一些分布式架构设计理解" class="headerlink" title="关于分布式算法和一些分布式架构设计理解"></a>关于分布式算法和一些分布式架构设计理解</h1><p>分布式系统是现代大规模应用的基础架构,本文将深入探讨分布式数据库的核心技术和设计理念,包括一致性协议、动态扩缩容、事务处理、故障恢复以及并发控制等关键方面。</p><h2 id="分布式数据库相关"><a href="#分布式数据库相关" class="headerlink" title="分布式数据库相关"></a>分布式数据库相关</h2><h3 id="如何设计分布式数据库的一致性协议"><a href="#如何设计分布式数据库的一致性协议" class="headerlink" title="如何设计分布式数据库的一致性协议"></a>如何设计分布式数据库的一致性协议</h3><p>在分布式系统中,一致性协议是保证数据一致性的关键机制。其中,Raft算法是一种被广泛应用的分布式一致性算法。</p><h4 id="Raft算法"><a href="#Raft算法" class="headerlink" title="Raft算法"></a>Raft算法</h4><h5 id="角色设计"><a href="#角色设计" class="headerlink" title="角色设计"></a>角色设计</h5><p>Raft算法中定义了三种角色:</p><ul><li><strong>Leader(镇长)</strong>:负责处理所有客户端请求,管理日志复制</li><li><strong>Follower(普通议员)</strong>:被动接收Leader的请求,参与数据记录和选举</li><li><strong>Candidate(候选人)</strong>:希望成为Leader的Follower,在选举过程中的临时角色</li></ul><h5 id="镇长失联"><a href="#镇长失联" class="headerlink" title="镇长失联"></a>镇长失联</h5><p>当Leader节点失联时,Raft算法通过以下机制选举新的Leader:</p><ul><li>每个Follower都有一个随机的选举超时时间(类似闹钟)</li><li>当某个Follower的超时时间到达,它会变成Candidate并发起投票</li><li>如果Candidate获得超过半数节点的支持,则成为新的Leader</li><li>如果多个Candidate同时竞选导致没有候选人获得半数以上选票,则重置选举计时器重新选举</li><li>议员通常会投票给日志更新、更完整的候选人</li></ul><h5 id="决策记录(日志复制)"><a href="#决策记录(日志复制)" class="headerlink" title="决策记录(日志复制)"></a>决策记录(日志复制)</h5><p>Raft的日志复制过程如下:</p><ol><li>客户端向Leader提交请求(居民向镇长提出建议)</li><li>Leader先将请求写入自己的日志</li><li>Leader向所有Follower发送AppendEntries请求,要求它们复制该日志条目</li><li>当超过半数的Follower确认写入日志后,Leader提交该日志条目(类似两阶段提交协议)</li><li>Leader通知所有Follower提交该日志条目</li><li>Leader向客户端返回操作结果</li></ol><h5 id="安全保证"><a href="#安全保证" class="headerlink" title="安全保证"></a>安全保证</h5><p>Raft通过以下机制保证系统的安全性:</p><ul><li>Leader会检查Follower的日志状态,并帮助那些日志不完整的节点补齐缺失的日志条目</li><li>只有包含了当前任期内所有已提交日志的节点才能成为Leader</li><li>Leader永远不会覆盖或删除自己的日志条目</li></ul><h5 id="网络分区"><a href="#网络分区" class="headerlink" title="网络分区"></a>网络分区</h5><p>当网络分区发生时:</p><ul><li>如果集群被分割成多个部分,只有包含多数节点的分区能够选出Leader并继续提供服务</li><li>少数节点分区无法选出Leader(因为无法获得多数票),会一直处于Follower状态</li><li>当网络恢复后,少数分区的节点会同步多数分区的日志,保证数据一致性</li></ul><h3 id="设计一个分布式数据库动态扩缩容策略"><a href="#设计一个分布式数据库动态扩缩容策略" class="headerlink" title="设计一个分布式数据库动态扩缩容策略"></a>设计一个分布式数据库动态扩缩容策略</h3><p>随着业务的增长或收缩,数据库集群需要能够动态地增加或减少节点。不良的扩缩容设计可能导致大量数据迁移和服务中断。</p><h4 id="一致性哈希算法"><a href="#一致性哈希算法" class="headerlink" title="一致性哈希算法"></a>一致性哈希算法</h4><p>一致性哈希是解决动态扩缩容问题的有效方案:</p><ul><li>将数据和节点映射到一个哈希环上</li><li>每个节点负责管理从自己到哈希环上顺时针方向下一个节点之间的数据</li><li>当新增节点时,只需要重新分配该节点顺时针方向上一个节点原本管理的部分数据</li><li>当删除节点时,该节点的数据只需要转移给顺时针方向的下一个节点</li></ul><p>这种方式大大减少了扩缩容时需要迁移的数据量。但是,简单的一致性哈希可能导致数据分布不均,因此引入了虚拟节点的概念:</p><ul><li>每个物理节点在哈希环上对应多个虚拟节点</li><li>虚拟节点均匀分布在哈希环上</li><li>这样可以使数据更均匀地分布,并且在节点增减时,负载变化更加平衡</li></ul><h4 id="数据迁移策略"><a href="#数据迁移策略" class="headerlink" title="数据迁移策略"></a>数据迁移策略</h4><p>扩缩容过程中的数据迁移策略主要有:</p><ol><li><p><strong>停服迁移</strong></p><ul><li>直接停止服务,完成数据迁移后再恢复服务</li><li>优点:实现简单</li><li>缺点:会导致服务中断,适合数据量较小的场景</li></ul></li><li><p><strong>双写策略</strong></p><ul><li>在新旧节点上同时写入数据</li><li>读取时先查询旧节点,找不到再查询新节点</li><li>当确认数据一致后,可以采用灰度发布方式逐步将流量从旧节点迁移到新节点</li><li>优点:无需停机,用户无感知</li><li>缺点:实现复杂,需要额外的一致性保证机制</li></ul></li></ol><h3 id="分布式数据库的事务处理机制"><a href="#分布式数据库的事务处理机制" class="headerlink" title="分布式数据库的事务处理机制"></a>分布式数据库的事务处理机制</h3><p>分布式事务是分布式数据库中的难点,主要有以下几种实现方式:</p><h4 id="两阶段提交(2PC)"><a href="#两阶段提交(2PC)" class="headerlink" title="两阶段提交(2PC)"></a>两阶段提交(2PC)</h4><p>两阶段提交是最基本的分布式事务协议,包括准备阶段和提交阶段。</p><h4 id="三阶段提交(3PC)"><a href="#三阶段提交(3PC)" class="headerlink" title="三阶段提交(3PC)"></a>三阶段提交(3PC)</h4><p>三阶段提交是对2PC的改进,分为三个阶段:</p><ol><li><strong>询问阶段(CanCommit)</strong>:协调者询问参与者是否可以执行事务</li><li><strong>预提交阶段(PreCommit)</strong>:协调者要求参与者准备提交事务</li><li><strong>提交阶段(DoCommit)</strong>:协调者通知参与者正式提交事务</li></ol><p>3PC相比2PC增加了超时机制,提高了可用性,但仍然无法完全解决协调者单点故障问题。</p><h4 id="SAGA模式"><a href="#SAGA模式" class="headerlink" title="SAGA模式"></a>SAGA模式</h4><p>SAGA是一种长事务解决方案:</p><ul><li>将一个分布式事务拆分为多个本地事务</li><li>每个本地事务都有对应的补偿事务</li><li>当某个本地事务失败时,执行已完成事务的补偿操作,而不是回滚所有事务</li></ul><p>例如,一次旅行预订包含机票、酒店、租车等多个独立环节,如果租车失败,不必取消已经预订的机票和酒店,而是寻找其他替代方案。</p><h4 id="一致性保证"><a href="#一致性保证" class="headerlink" title="一致性保证"></a>一致性保证</h4><p>分布式系统中的一致性级别:</p><ol><li><p><strong>强一致性</strong></p><ul><li>所有节点在同一时间看到的数据完全一致</li><li>类似于所有电视台播出相同的画面,如果有一家信号不好,所有人都需要等待</li><li>优点:数据始终一致</li><li>缺点:性能较低,可用性受影响</li></ul></li><li><p><strong>最终一致性</strong></p><ul><li>短时间内各节点的数据可能不一致,但经过一段时间后最终会达到一致状态</li><li>优点:提高了系统的可用性和性能</li><li>缺点:存在数据不一致的窗口期</li></ul></li></ol><h3 id="分布式数据库的故障恢复机制设计"><a href="#分布式数据库的故障恢复机制设计" class="headerlink" title="分布式数据库的故障恢复机制设计"></a>分布式数据库的故障恢复机制设计</h3><p>故障恢复是分布式系统必须考虑的关键问题。</p><h4 id="故障类型"><a href="#故障类型" class="headerlink" title="故障类型"></a>故障类型</h4><ol><li><p><strong>单节点故障</strong></p><ul><li>由集群管理器协调其他节点接管故障节点的事务</li><li>节点恢复后需要先同步日志才能重新加入工作</li></ul></li><li><p><strong>网络分区</strong></p><ul><li>被隔离的节点暂时停止服务</li><li>网络恢复后同步数据再恢复工作</li></ul></li><li><p><strong>数据损坏</strong></p><ul><li>管理员需要校验数据</li><li>从其他节点获取正确的数据副本进行恢复</li></ul></li></ol><h4 id="故障检测"><a href="#故障检测" class="headerlink" title="故障检测"></a>故障检测</h4><ol><li><p><strong>心跳检测</strong></p><ul><li>Leader定期向所有节点发送心跳信息</li><li>如果某个节点在超时时间内没有响应,则认为该节点可能出现故障</li></ul></li><li><p><strong>Gossip协议</strong></p><ul><li>不依赖中心节点,各节点之间互相传播信息</li><li>每个节点定期随机选择其他节点交换信息</li><li>信息会附带之前与其他节点的交流记录</li><li>最终信息会传遍整个集群</li></ul></li></ol><h4 id="恢复方法"><a href="#恢复方法" class="headerlink" title="恢复方法"></a>恢复方法</h4><ul><li><strong>日志重放</strong>:通过重放操作日志恢复数据</li><li><strong>快照恢复</strong>:从最近的快照开始恢复,然后重放快照之后的日志</li></ul><h3 id="分布式数据库的多版本并发控制-MVCC-实现"><a href="#分布式数据库的多版本并发控制-MVCC-实现" class="headerlink" title="分布式数据库的多版本并发控制(MVCC)实现"></a>分布式数据库的多版本并发控制(MVCC)实现</h3><p>MVCC是一种并发控制技术,允许数据库在同一时间维护同一数据的多个版本,从而实现非阻塞的读操作。</p><h4 id="MVCC工作原理"><a href="#MVCC工作原理" class="headerlink" title="MVCC工作原理"></a>MVCC工作原理</h4><p>分布式数据库中的MVCC类似于一个图书馆联盟:</p><ul><li>当有人修改一本书时,图书馆不会直接覆盖原书,而是创建一个新版本并标记时间戳,同时保存旧版本</li><li>每位读者进入图书馆时会获得一个时间戳,这个时间戳决定了他能看到哪个版本的书</li><li>读者只能看到在他进入图书馆之前已经完成的修改</li></ul><h4 id="全局时钟问题"><a href="#全局时钟问题" class="headerlink" title="全局时钟问题"></a>全局时钟问题</h4><p>MVCC在分布式环境中面临的主要挑战是全局时钟问题:</p><ul><li>需要一个时间戳服务器提供全局单调递增的时间戳</li><li>分布式事务ID需要满足全局唯一和单调递增的特性</li></ul><h4 id="分布式死锁检测"><a href="#分布式死锁检测" class="headerlink" title="分布式死锁检测"></a>分布式死锁检测</h4><p>在分布式环境中,死锁检测更加复杂:</p><ul><li>需要构建跨节点的事务等待关系图</li><li>定期检查等待图中是否存在环,环的存在表示发生了死锁</li><li>一旦检测到死锁,选择一个事务进行回滚,打破死锁</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>分布式数据库系统是一个复杂的工程,需要解决一致性、可用性、分区容错性等多方面的挑战。通过合理的算法和机制设计,可以构建高性能、高可靠性的分布式数据库系统,为大规模应用提供坚实的数据基础。</p>]]></content>
<summary type="html"><h1 id="关于分布式算法和一些分布式架构设计理解"><a href="#关于分布式算法和一些分布式架构设计理解" class="headerlink" title="关于分布式算法和一些分布式架构设计理解"></a>关于分布式算法和一些分布式架构设计理解</h1><p>分布</summary>
</entry>
<entry>
<title>后端场景设计第二弹</title>
<link href="https://eatbreads.github.io/posts/e91be1cf.html"/>
<id>https://eatbreads.github.io/posts/e91be1cf.html</id>
<published>2025-05-26T15:50:31.000Z</published>
<updated>2025-05-31T15:55:54.752Z</updated>
<content type="html"><![CDATA[<h1>后端场景设计第二弹</h1><h2 id="设计一个短链系统">设计一个短链系统</h2><h3 id="什么是短链">什么是短链</h3><p>类似一个完整的地址,容易写错,如:中国浙江省杭州市西湖区文三路778号,就需要使用一种简单的方法,如邮政编码A12345用来表示这个地址,邮局收到A12345就知道要寄到这里。短链系统即为这种重定向到真实完整地址的系统。</p><h3 id="设计方案">设计方案</h3><p>后端存储短链和长链的对应关系,当往数据库传入一条长链时,这条数据的对应id即可作为短链返回。</p><h2 id="设计一个订单超时取消功能">设计一个订单超时取消功能</h2><h3 id="方案一:用定时任务">方案一:用定时任务</h3><ul><li>隔一分钟轮询一次订单表,查询每个订单是否超时</li><li>缺点是时间不准确,订单量大时对数据库压力比较大</li></ul><h3 id="方案二:用消息队列">方案二:用消息队列</h3><ul><li>RocketMQ有提供延迟消息功能,类似闹钟一样,下单的时候设置一下十分钟后发来一条取消订单的消息</li></ul><h3 id="方案三:redis的zset">方案三:redis的zset</h3><ul><li>使用zset存储订单ID,score为过期时间</li><li>定时扫描过期的订单进行处理</li></ul><h2 id="设计一个分布式单例对象">设计一个分布式单例对象</h2><p>分布式单例即多进程中保证仅有一个的对象。</p><h3 id="实现方案">实现方案</h3><ol><li><strong>需要加分布式锁</strong>:多个进程竞争一个分布式锁,谁抢到锁谁就可以用</li><li><strong>外部存储</strong>:使用序列化的方式存储单例对象,使用完后要写回外部存储</li><li><strong>分布式锁和外部存储都可以用redis实现</strong></li></ol><h2 id="商家想要知道自己店铺卖的最好的Top50商品,如何实现?">商家想要知道自己店铺卖的最好的Top50商品,如何实现?</h2><h3 id="实现方案-2">实现方案</h3><ol><li><strong>首先排除数据库查询</strong>:不可能卖一个东西就对数据库排一次表</li><li><strong>使用redis中的zset</strong>:score是数量,value是商品ID</li><li><strong>查询方式</strong>:商家查看的时候直接查看zset里面的0-50就行</li><li><strong>更新方式</strong>:增加订单的时候直接改zset对应score+1即可</li></ol><h2 id="朋友圈点赞功能如何实现">朋友圈点赞功能如何实现</h2><h3 id="需要涉及的功能点">需要涉及的功能点</h3><ol><li><strong>存储点赞信息</strong></li><li><strong>取消点赞</strong></li><li><strong>点赞列表</strong></li></ol><h3 id="实现方案:使用redis的zset">实现方案:使用redis的zset</h3><ul><li><strong>key</strong>是此条朋友圈的id</li><li><strong>score</strong>是点赞时间</li><li><strong>value</strong>是点赞人id</li></ul><h2 id="如何实现分布式锁">如何实现分布式锁</h2><h3 id="实现方案-3">实现方案</h3><ol><li><strong>使用redis的setNX</strong>:设置成功表示获取锁成功</li><li><strong>使用ZooKeeper的临时有序节点</strong>:创建节点成功表示获取锁成功</li></ol><h2 id="如何统计每个接口每分钟的调用次数">如何统计每个接口每分钟的调用次数</h2><h3 id="实现方案-4">实现方案</h3><p>直接存内存的哈希表,key为接口名+时间戳,value为调用次数。</p><h2 id="如何设计一个文件上传系统">如何设计一个文件上传系统</h2><h3 id="主要核心点">主要核心点</h3><ol><li><p><strong>超大文件上传</strong></p><ul><li>前端分块传输,避免局部失败导致全部失败</li><li>下载的时候后端按照顺序分块发给前端</li></ul></li><li><p><strong>如何避免重复文件传输</strong></p><ul><li>不应该使用文件名判重</li><li>可以使用哈希摘要,判断两个文件的哈希摘要是否一致</li><li>哈希摘要也可用于判断文件是否被篡改</li></ul></li><li><p><strong>如何限流</strong></p><ul><li>限制文件最大大小、发送频次等</li></ul></li></ol><h2 id="如何设计一个分布式id发号器">如何设计一个分布式id发号器</h2><p>分布式id本质上是全局唯一id,如UUID,但UUID不适合作为组件,因为太长了。</p><h3 id="常见两种实现">常见两种实现</h3><ol><li><p><strong>雪花算法</strong></p><ul><li>可以生成一个64bit的id</li><li>前41个是时间戳,之后10个是机器号,保证了同一时间内由不同机器产生的uid不同</li><li>缺点是依赖时钟,若时钟回拨会发生重复</li></ul></li><li><p><strong>基于数据库实现</strong></p><ul><li>使用mysql的bitTag作为唯一索引,保证每个机器的初始位置不同</li><li>如两个数据库就一个1,3,5,7,一个为2,4,6,8</li></ul></li></ol>]]></content>
<summary type="html">详细介绍常见后端系统设计场景,包括RPC框架、秒杀系统、消息队列等核心技术的设计思路与实现方案</summary>
<category term="技术架构" scheme="https://eatbreads.github.io/categories/%E6%8A%80%E6%9C%AF%E6%9E%B6%E6%9E%84/"/>
<category term="分布式系统" scheme="https://eatbreads.github.io/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/"/>
<category term="系统设计" scheme="https://eatbreads.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="后端开发" scheme="https://eatbreads.github.io/tags/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
</entry>
<entry>
<title>后端场景设计第一弹</title>
<link href="https://eatbreads.github.io/posts/d90d0d17.html"/>
<id>https://eatbreads.github.io/posts/d90d0d17.html</id>
<published>2025-05-25T15:50:31.000Z</published>
<updated>2025-06-01T02:13:15.192Z</updated>
<content type="html"><![CDATA[<h2 id="如何设计RPC框架">如何设计RPC框架</h2><p>远程过程调用(Remote Procedure Call)的目的是让我们调用远程方法一样像本地方法一样没区别。</p><h3 id="核心组件">核心组件</h3><p>RPC框架主要包含四个核心部分:</p><ol><li><p><strong>顶层代理设计</strong></p><ul><li>提供统一的调用类,屏蔽底层细节</li><li>通过动态代理实现接口的远程调用</li></ul></li><li><p><strong>序列化/反序列化</strong></p><ul><li>将对象转换为二进制数据流</li><li>常用序列化协议:Protobuf、JSON、Hessian等</li></ul></li><li><p><strong>拼接协议/解析协议</strong></p><ul><li>定义请求和响应的数据格式</li><li>包含服务名、方法名、参数类型、参数值等信息</li></ul></li><li><p><strong>底层网络传输</strong></p><ul><li>基于TCP/UDP的网络通信</li><li>支持长连接、连接池等优化手段</li></ul></li></ol><h2 id="如何设计一个秒杀功能">如何设计一个秒杀功能</h2><h3 id="问题点">问题点</h3><ol><li><strong>瞬时流量的承接</strong></li><li><strong>防止超卖</strong></li><li><strong>防止黑产</strong></li><li><strong>避免正常服务受到影响</strong></li></ol><h3 id="前端解决方案">前端解决方案</h3><ol><li><strong>用CDN缓存资源,减少压力</strong></li><li><strong>在前端随机限流,降低请求量</strong></li><li><strong>按钮防抖,防止用户多次点击</strong></li></ol><h3 id="后端解决方案">后端解决方案</h3><ol><li><strong>用nginx做统一接入,实现负载均衡和限流</strong></li><li><strong>服务拆分,将秒杀功能拆分成独立的服务,避免其他功能受到影响</strong></li><li><strong>将秒杀数据拆分或缓存,可以使用分布式缓存或本地缓存</strong></li><li><strong>精准的库存扣减,防止超卖,此时需要加锁,数据库常用的是乐观锁</strong></li><li><strong>使用验证码答题等手段防止系统刷单</strong></li><li><strong>幂等操作防止重复加载</strong></li><li><strong>风控识别黑产,进行流量防控且需要动态黑名单</strong></li></ol><h2 id="如何设计一个消息队列">如何设计一个消息队列</h2><h3 id="重要角色">重要角色</h3><ol><li><strong>生产者</strong>:发送消息的一方</li><li><strong>消费者</strong>:接收消息的一方</li><li><strong>broker</strong>:消息中转站,负责存储和转发消息</li><li><strong>注册中心</strong>:用于broker/生产者/消费者的发现,即让生产者找到当前有什么可用的broker的ip和端口这些</li></ol><h3 id="流程">流程</h3><ol><li><strong>生产者生产消息发送到broker</strong></li><li><strong>消费者从broker中获取消息来消费</strong></li></ol><h2 id="如何设计一个线程池">如何设计一个线程池</h2><h3 id="什么是线程池">什么是线程池</h3><p>线程池说白了就是一个存储线程的容器,用于统一管理线程的创建和销毁。</p><h3 id="设计考虑点">设计考虑点</h3><ol><li><strong>初始线程数</strong>:线程池初始化时创建的线程数量</li><li><strong>最大线程数</strong>:线程池能够容纳的最大线程数量</li><li><strong>核心线程数</strong>:线程池运行起来后长期稳定的线程数,即使有空闲线程也不会被销毁</li><li><strong>任务的设计和执行</strong>:是否设计任务优先级</li><li><strong>超负荷如何解决</strong><ul><li>设置超时然后丢弃,也可以根据优先级处理</li><li>日志告警或者抛出异常</li></ul></li></ol><h2 id="如何设计一个哈希表">如何设计一个哈希表</h2><h3 id="哈希表是什么">哈希表是什么</h3><p>一个key-value的集合,通过将key进行哈希散列后对散列值取模,找到对应的value。</p><h3 id="设计要点">设计要点</h3><ol><li><strong>设计哈希函数</strong>:运算要快,还不能经常哈希碰撞</li><li><strong>解决哈希冲突</strong>:链表法、开放寻址法等</li><li><strong>若数组太大了则考虑转成红黑树</strong>:提高查询效率</li></ol>]]></content>
<summary type="html">详细介绍常见后端系统设计场景,包括RPC框架、秒杀系统、消息队列等核心技术的设计思路与实现方案</summary>
<category term="技术架构" scheme="https://eatbreads.github.io/categories/%E6%8A%80%E6%9C%AF%E6%9E%B6%E6%9E%84/"/>
<category term="分布式系统" scheme="https://eatbreads.github.io/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/"/>
<category term="系统设计" scheme="https://eatbreads.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="后端开发" scheme="https://eatbreads.github.io/tags/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
</entry>
<entry>
<title>leetcode刷题-滑动窗口-3-438</title>
<link href="https://eatbreads.github.io/posts/9e2906b8.html"/>
<id>https://eatbreads.github.io/posts/9e2906b8.html</id>
<published>2025-05-22T02:41:18.000Z</published>
<updated>2025-05-23T15:55:57.329Z</updated>
</entry>
<entry>
<title>LeetCode子串问题经典题目解析</title>
<link href="https://eatbreads.github.io/posts/fc21f42c.html"/>
<id>https://eatbreads.github.io/posts/fc21f42c.html</id>
<published>2025-05-22T02:39:24.000Z</published>
<updated>2025-05-26T15:40:47.324Z</updated>
<content type="html"><![CDATA[<h1>LeetCode子串问题经典题目解析</h1><h2 id="560-和为k的子数组">560. 和为k的子数组</h2><h3 id="解题思路">解题思路</h3><ul><li>使用前缀和 + 哈希表优化</li><li>子数组和可以表示为两个前缀和之差</li><li>一边计算前缀和一边记录到哈希表</li><li>查找是否存在 presum-k 的 前缀和</li></ul><h3 id="代码实现">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">subarraySum</span><span class="params">(vector<<span class="type">int</span>>& nums, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> map<<span class="type">int</span>,<span class="type">int</span>> mp;</span><br><span class="line"> mp[<span class="number">0</span>]=<span class="number">1</span>; <span class="comment">//处理空数组的情况</span></span><br><span class="line"> <span class="type">int</span> r=<span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> presum=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i<nums.<span class="built_in">size</span>();i++) {</span><br><span class="line"> presum +=nums[i];</span><br><span class="line"> r+=mp[presum-k];</span><br><span class="line"> mp[presum]++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> r;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h2 id="239-滑动窗口最大值">239. 滑动窗口最大值</h2><h3 id="解题思路-2">解题思路</h3><ul><li>使用哈希表记录元素出现次数</li><li>使用最大堆维护当前窗口最大值</li><li>移动窗口时:<ol><li>新元素加入堆和哈希表</li><li>删除元素从哈希表移除</li><li>堆顶元素不在哈希表中时弹出</li></ol></li></ul><h3 id="代码实现-2">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">maxSlidingWindow</span><span class="params">(vector<<span class="type">int</span>>& nums, <span class="type">int</span> k)</span> </span>{</span><br><span class="line"> <span class="keyword">auto</span> cmp = [](<span class="type">int</span> left, <span class="type">int</span> right) { <span class="keyword">return</span> left < right; };</span><br><span class="line"> priority_queue<<span class="type">int</span>, vector<<span class="type">int</span>>, <span class="keyword">decltype</span>(cmp)> <span class="built_in">maxHeap</span>(cmp);</span><br><span class="line"> unordered_map<<span class="type">int</span>,<span class="type">int</span>> count;</span><br><span class="line"> vector<<span class="type">int</span>> result;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 初始化窗口</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < k; i++) {</span><br><span class="line"> maxHeap.<span class="built_in">push</span>(nums[i]);</span><br><span class="line"> count[nums[i]]++;</span><br><span class="line"> }</span><br><span class="line"> result.<span class="built_in">push_back</span>(maxHeap.<span class="built_in">top</span>());</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 滑动窗口</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = k; i < nums.<span class="built_in">size</span>(); i++) {</span><br><span class="line"> count[nums[i-k]]--;</span><br><span class="line"> count[nums[i]]++;</span><br><span class="line"> maxHeap.<span class="built_in">push</span>(nums[i]);</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 移除堆顶无效元素</span></span><br><span class="line"> <span class="keyword">while</span>(!count[maxHeap.<span class="built_in">top</span>()]) {</span><br><span class="line"> maxHeap.<span class="built_in">pop</span>();</span><br><span class="line"> }</span><br><span class="line"> result.<span class="built_in">push_back</span>(maxHeap.<span class="built_in">top</span>());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h2 id="76-最小覆盖子串">76. 最小覆盖子串</h2><h3 id="解题思路-3">解题思路</h3><ul><li>使用两个哈希表:<ol><li>记录目标字符串中字符出现次数</li><li>记录当前窗口中字符出现次数</li></ol></li><li>使用滑动窗口:<ol><li>右指针扩展直到包含所有目标字符</li><li>左指针收缩优化长度</li><li>维护最小覆盖子串</li></ol></li></ul><h3 id="代码实现-3">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">string <span class="title">minWindow</span><span class="params">(string s, string t)</span> </span>{</span><br><span class="line"> unordered_map<<span class="type">char</span>, <span class="type">int</span>> need, window;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">char</span> c : t) need[c]++;</span><br><span class="line"> </span><br><span class="line"> <span class="type">int</span> left = <span class="number">0</span>, right = <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> valid = <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> start = <span class="number">0</span>, len = INT_MAX;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">while</span>(right < s.<span class="built_in">size</span>()) {</span><br><span class="line"> <span class="type">char</span> c = s[right];</span><br><span class="line"> right++;</span><br><span class="line"> <span class="keyword">if</span>(need.<span class="built_in">count</span>(c)) {</span><br><span class="line"> window[c]++;</span><br><span class="line"> <span class="keyword">if</span>(window[c] == need[c]) valid++;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">while</span>(valid == need.<span class="built_in">size</span>()) {</span><br><span class="line"> <span class="keyword">if</span>(right - left < len) {</span><br><span class="line"> start = left;</span><br><span class="line"> len = right - left;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="type">char</span> d = s[left];</span><br><span class="line"> left++;</span><br><span class="line"> <span class="keyword">if</span>(need.<span class="built_in">count</span>(d)) {</span><br><span class="line"> <span class="keyword">if</span>(window[d] == need[d]) valid--;</span><br><span class="line"> window[d]--;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> len == INT_MAX ? <span class="string">""</span> : s.<span class="built_in">substr</span>(start, len);</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h2 id="总结">总结</h2><p>子串问题的核心技巧:</p><ol><li>前缀和 + 哈希表优化</li><li>滑动窗口 + 数据结构维护</li><li>双指针 + 状态记录</li></ol><p>常见优化方向:</p><ul><li>空间换时间</li><li>合理使用数据结构</li><li>双指针减少遍历次数</li></ul>]]></content>
<summary type="html">详细分析LeetCode中的经典子串问题,包括和为k的子数组、滑动窗口最大值和最小覆盖子串</summary>
<category term="算法题解" scheme="https://eatbreads.github.io/categories/%E7%AE%97%E6%B3%95%E9%A2%98%E8%A7%A3/"/>
<category term="LeetCode" scheme="https://eatbreads.github.io/tags/LeetCode/"/>
<category term="算法" scheme="https://eatbreads.github.io/tags/%E7%AE%97%E6%B3%95/"/>
<category term="子串" scheme="https://eatbreads.github.io/tags/%E5%AD%90%E4%B8%B2/"/>
</entry>
<entry>
<title>Web框架业务层设计与实现</title>
<link href="https://eatbreads.github.io/posts/e75990a.html"/>
<id>https://eatbreads.github.io/posts/e75990a.html</id>
<published>2025-05-22T02:34:25.000Z</published>
<updated>2025-05-23T15:55:57.336Z</updated>
<content type="html"><![CDATA[<h1 id="Web框架业务层设计与实现"><a href="#Web框架业务层设计与实现" class="headerlink" title="Web框架业务层设计与实现"></a>Web框架业务层设计与实现</h1><h2 id="模块概述"><a href="#模块概述" class="headerlink" title="模块概述"></a>模块概述</h2><p>这是一个轻量级但功能完整的Web MVC框架,支持常见的Web应用功能,包括路由、控制器、请求处理、响应生成等。通过反射机制实现了优雅的控制器注册和方法调用。</p><h2 id="类结构设计"><a href="#类结构设计" class="headerlink" title="类结构设计"></a>类结构设计</h2><h3 id="1-Request类"><a href="#1-Request类" class="headerlink" title="1. Request类"></a>1. Request类</h3><p>处理HTTP请求:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Request</span> {</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> string m_method; <span class="comment">// 请求方法(GET/POST)</span></span><br><span class="line"> string m_uri; <span class="comment">// 完整URI</span></span><br><span class="line"> string m_path; <span class="comment">// 请求路径</span></span><br><span class="line"> string m_body; <span class="comment">// 请求体</span></span><br><span class="line"> Json m_post; <span class="comment">// POST数据</span></span><br><span class="line"> std::map<string, FileUpload> m_files; <span class="comment">// 上传文件</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure></p><h3 id="2-Response类"><a href="#2-Response类" class="headerlink" title="2. Response类"></a>2. Response类</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Response</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">html</span><span class="params">(<span class="type">const</span> string & data)</span></span>; <span class="comment">// 返回HTML</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">json</span><span class="params">(<span class="type">const</span> string & data)</span></span>; <span class="comment">// 返回JSON</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">render</span><span class="params">(<span class="type">const</span> string & filename)</span></span>; <span class="comment">// 渲染模板</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="type">int</span> m_code; <span class="comment">// 状态码</span></span><br><span class="line"> Type m_type; <span class="comment">// 响应类型</span></span><br><span class="line"> string m_data; <span class="comment">// 响应数据</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure><h3 id="3-Server类"><a href="#3-Server类" class="headerlink" title="3. Server类"></a>3. Server类</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Server</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">start</span><span class="params">()</span></span>; <span class="comment">// 启动服务器</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">bind</span><span class="params">(<span class="type">const</span> string & path, server_handler handler)</span></span>; <span class="comment">// 路由绑定</span></span><br><span class="line"> <span class="function">string <span class="title">handle</span><span class="params">(<span class="type">const</span> Request & req)</span></span>; <span class="comment">// 请求处理</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> std::map<string, server_handler> m_handlers; <span class="comment">// 路由表</span></span><br><span class="line"> string m_template_folder; <span class="comment">// 模板目录</span></span><br><span class="line"> string m_static_folder; <span class="comment">// 静态文件目录</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure><h3 id="4-控制器示例"><a href="#4-控制器示例" class="headerlink" title="4. 控制器示例"></a>4. 控制器示例</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Form</span> : <span class="keyword">public</span> Controller {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">index</span><span class="params">(<span class="type">const</span> Request & req, Response & resp)</span></span>; <span class="comment">// 渲染表单页面</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">reply</span><span class="params">(<span class="type">const</span> Request & req, Response & resp)</span></span>; <span class="comment">// 处理表单提交</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>继承于Controller就实现了/Form/reply的路由注册</p><h2 id="常见问题解答-Q-amp-A"><a href="#常见问题解答-Q-amp-A" class="headerlink" title="常见问题解答(Q&A)"></a>常见问题解答(Q&A)</h2><h3 id="Q1-请描述该Web框架的整体架构设计和主要组件?"><a href="#Q1-请描述该Web框架的整体架构设计和主要组件?" class="headerlink" title="Q1: 请描述该Web框架的整体架构设计和主要组件?"></a>Q1: 请描述该Web框架的整体架构设计和主要组件?</h3><p>A1: 框架主要包含以下核心组件:</p><ol><li><p>Server组件</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Server</span> {</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">start</span><span class="params">()</span></span>; <span class="comment">// 启动服务器</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">bind</span><span class="params">(<span class="type">const</span> string & path, server_handler handler)</span></span>; <span class="comment">// 路由绑定</span></span><br><span class="line"> <span class="function">string <span class="title">handle</span><span class="params">(<span class="type">const</span> Request & req)</span></span>; <span class="comment">// 请求处理</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> std::map<string, server_handler> m_handlers; <span class="comment">// 路由表</span></span><br><span class="line"> string m_template_folder; <span class="comment">// 模板目录</span></span><br><span class="line"> string m_static_folder; <span class="comment">// 静态资源目录</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>请求处理流程:</p></li></ol><ul><li>URL解析</li><li>路由匹配</li><li>控制器调用</li><li>响应生成</li></ul><h3 id="Q2-框架如何处理文件上传功能?"><a href="#Q2-框架如何处理文件上传功能?" class="headerlink" title="Q2: 框架如何处理文件上传功能?"></a>Q2: 框架如何处理文件上传功能?</h3><p>A2: 主要通过以下机制实现:</p><ol><li><p>FileUpload类:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">FileUpload</span> {</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">parse</span><span class="params">(<span class="type">const</span> <span class="type">char</span> * buf, <span class="type">int</span> len)</span></span>; <span class="comment">// 解析上传数据</span></span><br><span class="line"> <span class="function"><span class="type">bool</span> <span class="title">save</span><span class="params">(<span class="type">const</span> string & filename)</span></span>; <span class="comment">// 保存文件</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> string m_name; <span class="comment">// 表单字段名</span></span><br><span class="line"> string m_filename; <span class="comment">// 文件名</span></span><br><span class="line"> string m_type; <span class="comment">// 文件类型</span></span><br><span class="line">}; </span><br></pre></td></tr></table></figure></li><li><p>处理流程:</p></li></ol><ul><li>解析multipart/form-data</li><li>提取文件信息和内容</li><li>保存到指定目录</li></ul><h3 id="Q3-框架支持哪些响应类型?如何处理不同类型的响应?"><a href="#Q3-框架支持哪些响应类型?如何处理不同类型的响应?" class="headerlink" title="Q3: 框架支持哪些响应类型?如何处理不同类型的响应?"></a>Q3: 框架支持哪些响应类型?如何处理不同类型的响应?</h3><p>A3: 支持多种响应类型:</p><ol><li>Response类型枚举:</li></ol><ul><li>HTML</li><li>JSON</li><li>JS</li><li>CSS</li><li>图片(JPG/PNG/GIF)</li><li>ICO</li></ul><ol><li>响应处理示例:<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">Response::data</span><span class="params">(Type type, <span class="type">const</span> string & data)</span> </span>{</span><br><span class="line"> m_type = type;</span><br><span class="line"> m_data = data;</span><br><span class="line"> <span class="comment">// 根据类型设置不同的Content-Type</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h3 id="Q4-请详细描述框架的路由实现机制?"><a href="#Q4-请详细描述框架的路由实现机制?" class="headerlink" title="Q4: 请详细描述框架的路由实现机制?"></a>Q4: 请详细描述框架的路由实现机制?</h3><p>A4: 路由实现包含:</p><ol><li><p>URL解析:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">std::vector<string> arr = String::<span class="built_in">split</span>(String::<span class="built_in">trim</span>(path, <span class="string">" /"</span>), <span class="string">'/'</span>);</span><br><span class="line"><span class="comment">// 解析为控制器名和方法名</span></span><br></pre></td></tr></table></figure></li><li><p>路由匹配优先级:</p></li></ol><ul><li>显式路由绑定</li><li>静态资源匹配</li><li>控制器方法映射</li></ul><ol><li>反射调用:<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Object * ctrl = factory-><span class="built_in">create_class</span>(classname);</span><br><span class="line">ctrl-><span class="built_in">call</span>(methodname, req, resp);</span><br></pre></td></tr></table></figure></li></ol>]]></content>
<summary type="html">详细介绍Web框架业务层的设计实现,包括请求处理、路由、控制器等核心功能</summary>
<category term="系统设计" scheme="https://eatbreads.github.io/categories/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="C++" scheme="https://eatbreads.github.io/tags/C/"/>
<category term="Web框架" scheme="https://eatbreads.github.io/tags/Web%E6%A1%86%E6%9E%B6/"/>
<category term="MVC" scheme="https://eatbreads.github.io/tags/MVC/"/>
</entry>
<entry>
<title>Web框架反射模块设计与实现</title>
<link href="https://eatbreads.github.io/posts/451bf76a.html"/>
<id>https://eatbreads.github.io/posts/451bf76a.html</id>
<published>2025-05-22T02:30:39.000Z</published>
<updated>2025-05-22T02:33:40.822Z</updated>
<content type="html"><![CDATA[<h1 id="Web框架反射模块设计与实现"><a href="#Web框架反射模块设计与实现" class="headerlink" title="Web框架反射模块设计与实现"></a>Web框架反射模块设计与实现</h1><h2 id="模块概述"><a href="#模块概述" class="headerlink" title="模块概述"></a>模块概述</h2><p>这是一个轻量级的C++反射库,位于 <code>reflect</code> 目录下。主要实现了类、成员变量和成员函数的反射机制,支持运行时的动态创建对象、访问属性和调用方法。</p><h3 id="主要特性"><a href="#主要特性" class="headerlink" title="主要特性"></a>主要特性</h3><ul><li>支持类的动态创建和管理</li><li>支持成员变量的动态访问和修改</li><li>支持成员函数的动态调用</li><li>使用宏简化反射注册过程</li><li>线程安全的单例工厂模式</li></ul><p>这个反射库设计精巧,通过巧妙运用模板、宏和指针偏移等技术,实现了一个功能完整的反射系统。它的使用方式简单,性能开销小,是一个很好的轻量级反射解决方案。</p><h2 id="类结构设计"><a href="#类结构设计" class="headerlink" title="类结构设计"></a>类结构设计</h2><h3 id="1-Object类"><a href="#1-Object类" class="headerlink" title="1. Object类"></a>1. Object类</h3><ul><li>所有需要支持反射的类的基类</li><li>提供反射操作的基础接口</li></ul><h3 id="2-ClassFactory类"><a href="#2-ClassFactory类" class="headerlink" title="2. ClassFactory类"></a>2. ClassFactory类</h3><ul><li>反射系统的核心工厂类</li><li>管理所有已注册的类信息</li><li>实现单例模式</li></ul><h3 id="3-ClassField类"><a href="#3-ClassField类" class="headerlink" title="3. ClassField类"></a>3. ClassField类</h3><ul><li>封装类的成员变量信息</li><li>支持运行时的成员访问</li></ul><h3 id="4-ClassMethod类"><a href="#4-ClassMethod类" class="headerlink" title="4. ClassMethod类"></a>4. ClassMethod类</h3><ul><li>封装类的成员函数信息</li><li>支持运行时的方法调用</li></ul><h3 id="5-ClassRegister类"><a href="#5-ClassRegister类" class="headerlink" title="5. ClassRegister类"></a>5. ClassRegister类</h3><ul><li>提供反射注册的辅助功能</li><li>配合宏实现自动注册</li></ul><h2 id="常见问题解答-Q-amp-A"><a href="#常见问题解答-Q-amp-A" class="headerlink" title="常见问题解答(Q&A)"></a>常见问题解答(Q&A)</h2><h3 id="Q1-请详细描述项目中反射机制的核心实现原理?"><a href="#Q1-请详细描述项目中反射机制的核心实现原理?" class="headerlink" title="Q1: 请详细描述项目中反射机制的核心实现原理?"></a>Q1: 请详细描述项目中反射机制的核心实现原理?</h3><p>A1: 项目的反射机制主要通过以下几个方面实现:</p><ol><li><p>基类设计:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Object</span> {</span><br><span class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span> T></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">get</span><span class="params">(<span class="type">const</span> string & field_name, T & value)</span></span>;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span> T></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">set</span><span class="params">(<span class="type">const</span> string & field_name, <span class="type">const</span> T & value)</span></span>;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">template</span> <<span class="keyword">typename</span> R, <span class="keyword">typename</span> ...Args></span><br><span class="line"> <span class="function">R <span class="title">call</span><span class="params">(<span class="type">const</span> string & method_name, Args&&... args)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> string m_class_name;</span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>工厂模式:</p></li></ol><ul><li>使用单例的ClassFactory管理所有反射信息</li><li>通过map存储类名与创建函数的映射</li><li>支持运行时动态创建对象</li></ul><h3 id="Q2-项目如何实现成员变量的动态访问?内存对齐是否会影响反射?"><a href="#Q2-项目如何实现成员变量的动态访问?内存对齐是否会影响反射?" class="headerlink" title="Q2: 项目如何实现成员变量的动态访问?内存对齐是否会影响反射?"></a>Q2: 项目如何实现成员变量的动态访问?内存对齐是否会影响反射?</h3><p>A2: 主要通过以下机制实现:</p><ol><li><p>偏移量计算:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> REGISTER_CLASS_FIELD(className, fieldName, fieldType) \</span></span><br><span class="line"><span class="meta"> className className##fieldName; \</span></span><br><span class="line"><span class="meta"> ClassRegister classRegister##className##fieldName(#className, #fieldName, #fieldType, \</span></span><br><span class="line"><span class="meta"> (size_t)(&(className##fieldName.fieldName)) - (size_t)(&className##fieldName))</span></span><br></pre></td></tr></table></figure></li><li><p>访问实现:</p></li></ol><ul><li>使用指针偏移实现成员访问</li><li>考虑了内存对齐问题</li><li>通过模板实现类型安全</li></ul><h3 id="Q3-如何实现不同签名的成员函数的统一存储和调用?"><a href="#Q3-如何实现不同签名的成员函数的统一存储和调用?" class="headerlink" title="Q3: 如何实现不同签名的成员函数的统一存储和调用?"></a>Q3: 如何实现不同签名的成员函数的统一存储和调用?</h3><p>A3: 通过以下技术实现:</p><ol><li><p>函数指针统一化:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">ClassMethod</span> {</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> string m_name;</span><br><span class="line"> <span class="type">uintptr_t</span> m_method; <span class="comment">// 统一存储不同签名的函数指针</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure></li><li><p>函数调用:</p></li></ol><ul><li>使用std::function封装成员函数</li><li>通过模板和可变参数实现通用调用</li><li>运行时类型转换确保安全调用</li></ul><h3 id="Q4-项目中如何简化反射注册过程?宏定义的作用是什么?"><a href="#Q4-项目中如何简化反射注册过程?宏定义的作用是什么?" class="headerlink" title="Q4: 项目中如何简化反射注册过程?宏定义的作用是什么?"></a>Q4: 项目中如何简化反射注册过程?宏定义的作用是什么?</h3><p>A4: 通过以下方式简化:</p><ol><li><p>注册宏:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> REGISTER_CLASS(className)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> REGISTER_CLASS_FIELD(className, fieldName, fieldType)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> REGISTER_CLASS_METHOD(className, methodName, returnType, ...)</span></span><br></pre></td></tr></table></figure></li><li><p>实现原理:</p></li></ol><ul><li>自动生成创建函数</li><li>自动计算成员偏移</li><li>自动注册到工厂类</li></ul><h3 id="Q5-反射机制如何保证类型安全?如何处理类型转换错误?"><a href="#Q5-反射机制如何保证类型安全?如何处理类型转换错误?" class="headerlink" title="Q5: 反射机制如何保证类型安全?如何处理类型转换错误?"></a>Q5: 反射机制如何保证类型安全?如何处理类型转换错误?</h3><p>A5: 主要通过以下机制保证:</p><ol><li>编译期检查:</li></ol><ul><li>使用模板实现类型检查</li><li>存储类型信息</li><li>运行时类型验证</li></ul><ol><li>运行时保护:<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Object::get</span><span class="params">(<span class="type">const</span> string & field_name, T & value)</span> </span>{</span><br><span class="line"> ClassField * field = Singleton<ClassFactory>::<span class="built_in">instance</span>()-><span class="built_in">get_class_field</span>(m_class_name, field_name);</span><br><span class="line"> <span class="keyword">if</span> (field == <span class="literal">nullptr</span>) <span class="keyword">return</span>;</span><br><span class="line"> <span class="comment">// 类型安全的指针操作</span></span><br><span class="line"> value = *((T *)((<span class="type">unsigned</span> <span class="type">char</span> *)(<span class="keyword">this</span>) + field-><span class="built_in">offset</span>()));</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol>]]></content>
<summary type="html">详细介绍Web框架中反射模块的设计实现,包括核心类结构和关键技术点分析</summary>
<category term="系统设计" scheme="https://eatbreads.github.io/categories/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="C++" scheme="https://eatbreads.github.io/tags/C/"/>
<category term="系统设计" scheme="https://eatbreads.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="反射" scheme="https://eatbreads.github.io/tags/%E5%8F%8D%E5%B0%84/"/>
</entry>
<entry>
<title>Web框架Thread模块设计与实现</title>
<link href="https://eatbreads.github.io/posts/5e8acb82.html"/>
<id>https://eatbreads.github.io/posts/5e8acb82.html</id>
<published>2025-05-18T15:46:38.000Z</published>
<updated>2025-05-21T15:48:28.176Z</updated>
<content type="html"><![CDATA[<h1>Web框架Thread模块设计与实现</h1><h2 id="模块概述">模块概述</h2><p>Thread模块是整个框架的并发处理核心,采用面向对象的设计实现了线程池和任务调度功能。该模块位于 <code>thread</code> 目录下。</p><h2 id="类结构设计">类结构设计</h2><h3 id="1-Thread基类">1. Thread基类</h3><ul><li>提供了start、stop和一个run纯虚函数供子类 实现</li></ul><h3 id="2-WorkerThread类">2. WorkerThread类</h3><ul><li>具体的工作线程类</li><li>run函数内部会执行task任务</li><li>assign函数可以给他赋值当前task,然后唤醒run函数继续处理新任务</li></ul><h3 id="3-ThreadPool类">3. ThreadPool类</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">ThreadPool</span> {</span><br><span class="line"> std::list<WorkerThread*> m_pool; <span class="comment">// 装载了线程</span></span><br><span class="line"> <span class="comment">// 提供assign(Task* task)方法丢入工作线程执行</span></span><br><span class="line">};</span><br></pre></td></tr></table></figure><h3 id="4-TaskDispatcher类">4. TaskDispatcher类</h3><ul><li>相当于又包装了一层threadPool</li><li>使得赋值task不需要直接操作threadpool</li></ul><h2 id="常见问题解答-Q-A">常见问题解答(Q&A)</h2><h3 id="Q1-请详细描述项目中线程池的实现原理,以及如何保证线程安全?">Q1: 请详细描述项目中线程池的实现原理,以及如何保证线程安全?</h3><p>A1: 线程池实现主要包含以下几个方面:</p><ol><li>核心组件:</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">ThreadPool</span> {</span><br><span class="line"> std::list<WorkerThread*> m_pool; <span class="comment">// 线程池容器</span></span><br><span class="line"> Mutex m_mutex; <span class="comment">// 互斥锁</span></span><br><span class="line"> Condition m_cond; <span class="comment">// 条件变量</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li>线程安全保证:</li></ol><ul><li>使用RAII方式的 <code>auto_lock.cpp</code> 确保锁的自动释放</li><li>条件变量实现线程同步</li><li>任务队列的原子操作</li></ul><h3 id="Q2-项目中TaskDispatcher是如何实现任务分发的?如何处理任务队列满的情况?">Q2: 项目中TaskDispatcher是如何实现任务分发的?如何处理任务队列满的情况?</h3><p>A2: 任务调度主要通过以下机制实现:</p><ol><li>任务分发流程:</li></ol><ul><li>先尝试直接分配给空闲线程</li><li>如果没有空闲线程,将任务放入队列前端</li><li>使用条件变量通知工作线程</li></ul><ol start="2"><li>处理策略:</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">TaskDispatcher::handle</span><span class="params">(Task * task)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (!pool-><span class="built_in">empty</span>()) {</span><br><span class="line"> pool-><span class="built_in">assign</span>(task);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 所有线程忙碌时,将任务放回队列前端</span></span><br><span class="line"> m_queue.<span class="built_in">push_front</span>(task);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Q3-项目中如何预防死锁?如何处理线程异常?">Q3: 项目中如何预防死锁?如何处理线程异常?</h3><p>A3: 主要通过以下机制:</p><ol><li>死锁预防:</li></ol><ul><li>使用RAII技术管理锁资源</li><li>统一的加锁顺序</li><li>使用条件变量避免忙等待</li></ul><ol start="2"><li>异常处理:</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">WorkerThread::run</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">pthread_cleanup_push</span>(cleanup, <span class="keyword">this</span>);</span><br><span class="line"> <span class="comment">// ... 业务逻辑 ...</span></span><br><span class="line"> <span class="built_in">pthread_cleanup_pop</span>(<span class="number">1</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Q4-为什么要在工作线程中屏蔽信号?如何实现的?">Q4: 为什么要在工作线程中屏蔽信号?如何实现的?</h3><p>A4: 信号处理的考虑:</p><ol><li>屏蔽原因:</li></ol><ul><li>避免信号处理程序干扰正常业务逻辑</li><li>统一在主线程处理信号</li></ul><ol start="2"><li>实现方式:</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">sigset_t</span> mask;</span><br><span class="line"><span class="built_in">sigfillset</span>(&mask);</span><br><span class="line"><span class="built_in">pthread_sigmask</span>(SIG_SETMASK, &mask, <span class="literal">nullptr</span>);</span><br></pre></td></tr></table></figure><h3 id="Q5-如何处理线程池满载情况?是否支持动态扩容?">Q5: 如何处理线程池满载情况?是否支持动态扩容?</h3><p>A5: 处理策略:</p><ol><li>当前实现:</li></ol><ul><li>使用任务队列缓存任务</li><li>记录警告日志</li><li>等待空闲线程</li></ul><ol start="2"><li>优化建议:</li></ol><ul><li>可以添加动态扩容机制</li><li>实现任务优先级</li><li>添加任务超时机制</li></ul><h3 id="Q6-项目中如何确保线程资源的正确释放?">Q6: 项目中如何确保线程资源的正确释放?</h3><p>A6: 通过以下机制保证:</p><ol><li>线程资源:</li></ol><ul><li>使用RAII管理线程生命周期</li><li>清理函数确保资源释放</li><li>线程池统一管理</li></ul>]]></content>
<summary type="html">详细介绍Web框架中Thread模块的设计实现,包括线程池、任务调度等核心功能</summary>
<category term="系统设计" scheme="https://eatbreads.github.io/categories/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="多线程" scheme="https://eatbreads.github.io/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/"/>
<category term="C++" scheme="https://eatbreads.github.io/tags/C/"/>
<category term="系统设计" scheme="https://eatbreads.github.io/tags/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
</entry>
<entry>
<title>web模块介绍-网络socket篇-含QA</title>
<link href="https://eatbreads.github.io/posts/8fc563d2.html"/>
<id>https://eatbreads.github.io/posts/8fc563d2.html</id>
<published>2025-05-17T15:31:22.000Z</published>
<updated>2025-05-17T15:36:03.353Z</updated>
<content type="html"><![CDATA[<h1>Web框架Socket模块设计与实现</h1><h2 id="模块概述">模块概述</h2><p>Socket模块是整个Web框架的网络通信基础,采用面向对象的设计方式,实现了TCP网络通信的完整功能。</p><h2 id="类结构设计">类结构设计</h2><h3 id="1-基础Socket类-socket-h">1. 基础Socket类 (socket.h)</h3><ul><li>提供统一的接口:bind、listen、connect、accept等</li><li>实现了多个socket优化配置选项</li></ul><h3 id="2-服务端Socket和客户端Socket">2. 服务端Socket和客户端Socket</h3><ul><li>继承于socket基类</li><li>对业务进行针对性简化</li></ul><h3 id="3-Socket处理器-socket-handler-h">3. Socket处理器 (socket_handler.h)</h3><ul><li>内置epoll和服务器监听句柄(服务器唯一实例)</li><li>内部提供handler接口对新连接执行处理(获取工厂实例,assign任务)</li></ul><h2 id="常见问题解答-Q-A">常见问题解答(Q&A)</h2><h3 id="Q1-项目中使用了epoll进行IO多路复用,为什么选择epoll而不是select-poll?epoll的EPOLLONESHOT标志位的作用是什么?">Q1: 项目中使用了epoll进行IO多路复用,为什么选择epoll而不是select/poll?epoll的EPOLLONESHOT标志位的作用是什么?</h3><p>A1: 这个问题可以从以下几个方面回答:</p><ol><li><p>epoll相比select/poll的优势:</p><ul><li>select/poll每次调用都需要将fd集合从用户态拷贝到内核态,而epoll通过mmap实现内核与用户空间的共享内存</li><li>select/poll都需要遍历整个fd集合,而epoll采用回调机制,只关注发生事件的fd</li><li>select最大支持1024个fd,poll没有限制但性能会随fd数量增长而下降,epoll则基本不受限制</li></ul></li><li><p>在代码中EPOLLONESHOT的使用:</p></li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">SocketHandler::attach</span><span class="params">(<span class="type">int</span> sockfd)</span> </span>{</span><br><span class="line"> m_epoll.<span class="built_in">add</span>(sockfd, (EPOLLIN | EPOLLHUP | EPOLLERR | EPOLLONESHOT));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>EPOLLONESHOT确保一个socket连接在任意时刻只被一个线程处理,防止多线程下的并发问题。</p><h3 id="Q2-项目中ServerSocket的构造函数中设置了多个socket选项,请解释这些选项的作用及其对性能的影响。">Q2: 项目中ServerSocket的构造函数中设置了多个socket选项,请解释这些选项的作用及其对性能的影响。</h3><p>A2: 参考 <code>server_socket.cpp</code> 中的实现:</p><ol><li>set_recv_buffer/set_send_buffer : 设置10KB的收发缓冲区,用于调节数据传输的缓冲大小</li><li>set_linger : 控制socket关闭时的行为,设置为true且timeout为0表示立即关闭</li><li>set_keepalive : 保持连接活跃,定期检测连接状态</li><li>set_reuseaddr : 允许地址重用,服务器重启时可以立即绑定端口</li></ol><h3 id="Q3-项目中如何处理socket的异常情况?比如客户端异常断开、连接超时等。">Q3: 项目中如何处理socket的异常情况?比如客户端异常断开、连接超时等。</h3><p>A3: 主要通过以下机制处理:</p><ol><li>epoll事件监控:</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (m_epoll.<span class="built_in">is_set</span>(i, EPOLLHUP)) {</span><br><span class="line"> <span class="built_in">log_error</span>(<span class="string">"socket hang up by peer: conn=%d"</span>, connfd);</span><br><span class="line"> Singleton<TaskFactory>::<span class="built_in">instance</span>()-><span class="built_in">remove</span>(connfd);</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (m_epoll.<span class="built_in">is_set</span>(i, EPOLLERR)) {</span><br><span class="line"> <span class="built_in">log_error</span>(<span class="string">"socket error: conn=%d"</span>, connfd);</span><br><span class="line"> Singleton<TaskFactory>::<span class="built_in">instance</span>()-><span class="built_in">remove</span>(connfd);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li>资源清理:</li></ol><ul><li>使用TaskFactory管理连接对应的任务</li><li>及时清理断开的连接</li><li>完善的错误日志记录</li></ul><h3 id="Q4-项目中Socket模块使用了哪些设计模式?为什么要使用这些模式?">Q4: 项目中Socket模块使用了哪些设计模式?为什么要使用这些模式?</h3><p>A4: 主要使用了以下设计模式:</p><ol><li>单例模式:SocketHandler采用单例模式,确保全局只有一个socket管理器</li><li>工厂模式:TaskFactory负责创建和管理任务</li><li>策略模式:通过继承Socket基类实现ServerSocket和ClientSocket,提供不同的连接策略</li></ol><h3 id="Q5-项目如何保证长连接的稳定性?如何处理心跳检测?">Q5: 项目如何保证长连接的稳定性?如何处理心跳检测?</h3><p>A5: 主要通过以下机制实现:</p><ol><li>keepalive机制:</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Socket::set_keepalive</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="type">int</span> flag = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">setsockopt</span>(m_sockfd, SOL_SOCKET, SO_KEEPALIVE, &flag, <span class="built_in">sizeof</span>(flag)) < <span class="number">0</span>) {</span><br><span class="line"> <span class="built_in">log_error</span>(<span class="string">"socket set_keep_alive error: errno=%d errmsg=%s"</span>, errno, <span class="built_in">strerror</span>(errno));</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="2"><li>超时检测:</li></ol><ul><li>通过epoll的timeout参数实现超时检测</li><li>配合TaskFactory管理连接状态</li><li>异常情况及时清理资源</li></ul>]]></content>
<summary type="html">详细介绍Web框架中Socket模块的设计实现,包括类结构、核心功能和常见问题解答</summary>
<category term="系统设计" scheme="https://eatbreads.github.io/categories/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1/"/>
<category term="C++" scheme="https://eatbreads.github.io/tags/C/"/>
<category term="网络编程" scheme="https://eatbreads.github.io/tags/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/"/>
<category term="Socket" scheme="https://eatbreads.github.io/tags/Socket/"/>
</entry>
<entry>
<title>LeetCode双指针经典题目解析</title>
<link href="https://eatbreads.github.io/posts/aec0840e.html"/>
<id>https://eatbreads.github.io/posts/aec0840e.html</id>
<published>2025-05-16T15:38:24.000Z</published>
<updated>2025-05-17T02:36:46.724Z</updated>
<content type="html"><![CDATA[<h1>LeetCode双指针经典题目解析</h1><h2 id="283-移动零">283. 移动零</h2><h3 id="解题思路">解题思路</h3><ul><li>使用双指针技巧</li><li>左指针标记当前需要填充非零数的位置</li><li>右指针遍历数组寻找非零数</li><li>遇到非零数就交换两个指针位置的值</li></ul><h3 id="代码实现">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">moveZeroes</span><span class="params">(vector<<span class="type">int</span>>& nums)</span> </span>{</span><br><span class="line"> <span class="type">int</span> start = <span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> size = nums.<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i < size ; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(nums[i] != <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">swap</span>(nums[start++],nums[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="11-盛最多水的容器">11. 盛最多水的容器</h2><h3 id="解题思路-2">解题思路</h3><ul><li>使用左右双指针向中间收缩</li><li>每次移动较短的那个边</li><li>计算过程中维护最大面积</li><li>面积计算:宽度(右指针-左指针)* 高度(两指针高度的较小值)</li></ul><h3 id="代码实现-2">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">maxArea</span><span class="params">(vector<<span class="type">int</span>>& height)</span> </span>{</span><br><span class="line"> <span class="type">int</span> left = <span class="number">0</span>; </span><br><span class="line"> <span class="type">int</span> right = height.<span class="built_in">size</span>()<span class="number">-1</span>;</span><br><span class="line"> <span class="type">int</span> maxA = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(left < right)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> minheight = <span class="built_in">min</span>(height[left],height[right]);</span><br><span class="line"> <span class="type">int</span> vol = minheight * (right - left);</span><br><span class="line"></span><br><span class="line"> maxA = <span class="built_in">max</span>(maxA,vol);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(height[right]<height[left])</span><br><span class="line"> {</span><br><span class="line"> right--;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> left++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxA;</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="15-三数之和">15. 三数之和</h2><h3 id="解题思路-3">解题思路</h3><ul><li>先将数组排序</li><li>固定第一个数,然后用双指针寻找另外两个数</li><li>注意去重处理:<ol><li>固定数字时跳过重复值</li><li>左右指针移动时也要跳过重复值</li></ol></li><li>优化:<ol><li>当固定数字大于0时可以直接break</li><li>当和大于0时右指针左移,小于0时左指针右移</li></ol></li></ul><h3 id="代码实现-3">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> vector<vector<<span class="type">int</span>>> <span class="built_in">threeSum</span>(vector<<span class="type">int</span>>& nums) {</span><br><span class="line"> <span class="built_in">sort</span>(nums.<span class="built_in">begin</span>(),nums.<span class="built_in">end</span>());</span><br><span class="line"> <span class="type">int</span> size = nums.<span class="built_in">size</span>();</span><br><span class="line"> vector<vector<<span class="type">int</span>>> ret;</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i< size; i++)</span><br><span class="line"> { </span><br><span class="line"> <span class="keyword">if</span>(i!=<span class="number">0</span>&&nums[i]==nums[i<span class="number">-1</span>]) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="type">int</span> target = <span class="number">0</span> - nums[i];</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> left = i<span class="number">+1</span>;</span><br><span class="line"> <span class="type">int</span> right = size <span class="number">-1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span>(left < right)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span>(nums[left]+nums[right]<target)</span><br><span class="line"> {</span><br><span class="line"> left++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(nums[left]+nums[right]>target)</span><br><span class="line"> {</span><br><span class="line"> right--;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> {</span><br><span class="line"> ret.<span class="built_in">push_back</span>({nums[i],nums[left],nums[right]});</span><br><span class="line"> <span class="type">int</span> pre = nums[left];</span><br><span class="line"> <span class="keyword">while</span>(left<right && pre == nums[left])left++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="42-接雨水">42. 接雨水</h2><h3 id="解题思路-4">解题思路</h3><ul><li>双指针法:<ol><li>使用左右指针从两端向中间移动</li><li>维护左右两边的最大高度</li><li>较低的一边可以确定当前位置能接的雨水</li><li>移动较低的一边的指针</li></ol></li></ul><h3 id="代码实现-4">代码实现</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">trap</span><span class="params">(vector<<span class="type">int</span>>& h)</span> </span>{</span><br><span class="line"> <span class="comment">//记录每一根柱子左右的最大值中的最小值,若没有同时有比他自身大的最大值则设置为0</span></span><br><span class="line"> <span class="type">int</span> ret=<span class="number">0</span>;</span><br><span class="line"> <span class="type">int</span> m=<span class="number">0</span>;<span class="comment">//除柱子本身前缀最大值</span></span><br><span class="line"> <span class="type">int</span> n=h.<span class="built_in">size</span>();</span><br><span class="line"> vector<<span class="type">int</span>><span class="built_in">a</span>(n,<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">0</span>;i<n;i++){</span><br><span class="line"> <span class="keyword">if</span>(m>h[i])</span><br><span class="line"> a[i]=m;</span><br><span class="line"> <span class="keyword">else</span> a[i]=<span class="number">0</span>;</span><br><span class="line"> m=<span class="built_in">max</span>(m,h[i]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> m=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i=n<span class="number">-1</span>;i>=<span class="number">0</span>;i--){</span><br><span class="line"> <span class="keyword">if</span>(m>h[i])</span><br><span class="line"> a[i]=<span class="built_in">min</span>(m,a[i]);</span><br><span class="line"> <span class="keyword">else</span> a[i]=<span class="number">0</span>;</span><br><span class="line"> m=<span class="built_in">max</span>(m,h[i]);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">0</span>;i<n;i++){</span><br><span class="line"> <span class="keyword">if</span>(a[i])</span><br><span class="line"> ret+=a[i]-h[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">详细分析LeetCode中的经典双指针题目,包括移动零、盛水容器、三数之和等题目</summary>
<category term="算法题解" scheme="https://eatbreads.github.io/categories/%E7%AE%97%E6%B3%95%E9%A2%98%E8%A7%A3/"/>
<category term="LeetCode" scheme="https://eatbreads.github.io/tags/LeetCode/"/>
<category term="算法" scheme="https://eatbreads.github.io/tags/%E7%AE%97%E6%B3%95/"/>
<category term="双指针" scheme="https://eatbreads.github.io/tags/%E5%8F%8C%E6%8C%87%E9%92%88/"/>
</entry>
<entry>
<title>LeetCode哈希表经典题目解析</title>
<link href="https://eatbreads.github.io/posts/b7b164ae.html"/>
<id>https://eatbreads.github.io/posts/b7b164ae.html</id>
<published>2025-05-15T15:38:24.000Z</published>
<updated>2025-05-15T15:41:46.633Z</updated>
<content type="html"><![CDATA[<h1>LeetCode哈希表经典题目解析</h1><h2 id="1-两数之和">1. 两数之和</h2><h3 id="解法分析">解法分析</h3><h4 id="1-暴力枚举">1 暴力枚举</h4><ul><li>时间复杂度:O(n²)</li><li>空间复杂度:O(1)</li><li>思路:对每个元素x,枚举寻找target-x</li></ul><h4 id="2-排序双指针">2 排序双指针</h4><ul><li>时间复杂度:O(nlogn)</li><li>空间复杂度:O(n)</li><li>思路:<ol><li>用结构体保存值和原始下标</li><li>排序后从首尾向中间遍历</li><li>根据和与目标值的比较决定移动方向</li></ol></li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">A</span></span><br><span class="line">{</span><br><span class="line"> <span class="type">int</span> value;</span><br><span class="line"> <span class="type">int</span> index;</span><br><span class="line"> <span class="built_in">A</span>()=<span class="keyword">default</span>;</span><br><span class="line"> <span class="built_in">A</span>(<span class="type">int</span> v,<span class="type">int</span> i){value=v;index=i;}</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">twoSum</span><span class="params">(vector<<span class="type">int</span>>& nums, <span class="type">int</span> target)</span> </span>{</span><br><span class="line"> vector<A> vec;</span><br><span class="line"> vec.<span class="built_in">resize</span>(nums.<span class="built_in">size</span>());</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i =<span class="number">0</span>;i<nums.<span class="built_in">size</span>();i++)</span><br><span class="line"> {</span><br><span class="line"> vec[i] = {nums[i],i};</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">sort</span>(vec.<span class="built_in">begin</span>(),vec.<span class="built_in">end</span>(),[](A x,A y){</span><br><span class="line"> <span class="keyword">return</span> x.value<y.value;</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="type">int</span> left =<span class="number">0</span>, right = vec.<span class="built_in">size</span>()<span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">while</span>(left<right)</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> sum = vec[left].value+vec[right].value;</span><br><span class="line"> <span class="keyword">if</span>(sum<target)</span><br><span class="line"> left++;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(sum>target)</span><br><span class="line"> right--;</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">return</span> {vec[left].index,vec[right].index};</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {vec[left].index,vec[right].index};</span><br><span class="line"> };</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="3-哈希表">3 哈希表</h4><ul><li>时间复杂度:O(n)</li><li>空间复杂度:O(n)</li><li>思路:<ol><li>哈希表key存储值,value存储下标</li><li>遍历过程中查找target-x</li><li>没找到则将当前值加入哈希表</li></ol></li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function">vector<<span class="type">int</span>> <span class="title">twoSum</span><span class="params">(vector<<span class="type">int</span>>& nums, <span class="type">int</span> target)</span> </span>{</span><br><span class="line"> unordered_map<<span class="type">int</span>, <span class="type">int</span>> hashMap; <span class="comment">// 创建哈希表</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < nums.<span class="built_in">size</span>(); i++) {</span><br><span class="line"> <span class="type">int</span> complement = target - nums[i]; <span class="comment">// 计算差值</span></span><br><span class="line"> <span class="comment">// 在哈希表中查找差值</span></span><br><span class="line"> <span class="keyword">if</span> (hashMap.<span class="built_in">find</span>(complement) != hashMap.<span class="built_in">end</span>()) {</span><br><span class="line"> <span class="keyword">return</span> {hashMap[complement], i}; <span class="comment">// 找到返回下标</span></span><br><span class="line"> }</span><br><span class="line"> hashMap[nums[i]] = i; <span class="comment">// 存入哈希表</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {}; <span class="comment">// 没有找到返回空数组</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="49-字母异位词分组">49. 字母异位词分组</h2><h3 id="解法分析-2">解法分析</h3><h4 id="哈希表法">哈希表法</h4><ul><li>时间复杂度:O(nklogk),k是字符串的最大长度</li><li>空间复杂度:O(nk)</li><li>思路:<ol><li>key为排序后的字符串</li><li>value为原始字符串数组</li><li>最后遍历哈希表整理结果</li></ol></li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> vector<vector<string>> <span class="built_in">groupAnagrams</span>(vector<string>& strs) {</span><br><span class="line"> map<string,vector<string>> mp;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> & str: strs)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">auto</span> s = str;</span><br><span class="line"> <span class="built_in">sort</span>(str.<span class="built_in">begin</span>(),str.<span class="built_in">end</span>());</span><br><span class="line"> mp[str].<span class="built_in">emplace_back</span>(s);</span><br><span class="line"> }</span><br><span class="line"> vector<vector<string>> ret;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> & kv: mp)</span><br><span class="line"> {</span><br><span class="line"> ret.<span class="built_in">emplace_back</span>(kv.second);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="128-最长连续序列">128. 最长连续序列</h2><h3 id="解法分析-3">解法分析</h3><h4 id="哈希集合">哈希集合</h4><ul><li>时间复杂度:O(n)</li><li>空间复杂度:O(n)</li><li>思路:<ol><li>将所有数字加入集合</li><li>遍历每个数x,寻找x+1, x+2…和x-1, x-2…</li><li>边遍历边从集合中删除</li><li>维护最大长度</li></ol></li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">int</span> <span class="title">longestConsecutive</span><span class="params">(vector<<span class="type">int</span>>& nums)</span> </span>{</span><br><span class="line"> unordered_set<<span class="type">int</span>> st;</span><br><span class="line"> <span class="type">int</span> count = nums.<span class="built_in">size</span>();</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i<count;i++)</span><br><span class="line"> {</span><br><span class="line"> st.<span class="built_in">insert</span>(nums[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="type">int</span> maxlen = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(!st.<span class="built_in">empty</span>())</span><br><span class="line"> {</span><br><span class="line"> <span class="type">int</span> num = *(st.<span class="built_in">begin</span>());</span><br><span class="line"> st.<span class="built_in">erase</span>(num);</span><br><span class="line"> </span><br><span class="line"> <span class="type">int</span> cnt = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int</span> a=<span class="number">1</span>,b=<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span>(st.<span class="built_in">find</span>(num+a)!=st.<span class="built_in">end</span>())</span><br><span class="line"> {</span><br><span class="line"> st.<span class="built_in">erase</span>(num+a);</span><br><span class="line"> cnt++; a++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(st.<span class="built_in">find</span>(num-b)!=st.<span class="built_in">end</span>())</span><br><span class="line"> {</span><br><span class="line"> st.<span class="built_in">erase</span>(num-b);</span><br><span class="line"> cnt++; b++;</span><br><span class="line"> }</span><br><span class="line"> maxlen = <span class="built_in">max</span>(cnt,maxlen);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxlen;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">详细分析LeetCode中的经典哈希表题目,包括两数之和、字母异位词分组和最长连续序列</summary>
<category term="算法题解" scheme="https://eatbreads.github.io/categories/%E7%AE%97%E6%B3%95%E9%A2%98%E8%A7%A3/"/>
<category term="LeetCode" scheme="https://eatbreads.github.io/tags/LeetCode/"/>
<category term="算法" scheme="https://eatbreads.github.io/tags/%E7%AE%97%E6%B3%95/"/>
<category term="哈希表" scheme="https://eatbreads.github.io/tags/%E5%93%88%E5%B8%8C%E8%A1%A8/"/>
</entry>
<entry>
<title>比特币交易系统升级:UTXO集合与Merkle树实现</title>
<link href="https://eatbreads.github.io/posts/9842f704.html"/>
<id>https://eatbreads.github.io/posts/9842f704.html</id>
<published>2025-05-13T15:48:18.000Z</published>
<updated>2025-05-13T15:51:33.884Z</updated>
<content type="html"><![CDATA[<h1 id="比特币交易系统升级:UTXO集合与Merkle树"><a href="#比特币交易系统升级:UTXO集合与Merkle树" class="headerlink" title="比特币交易系统升级:UTXO集合与Merkle树"></a>比特币交易系统升级:UTXO集合与Merkle树</h1><h2 id="UTXO集合优化"><a href="#UTXO集合优化" class="headerlink" title="UTXO集合优化"></a>UTXO集合优化</h2><h3 id="1-为什么需要UTXO集合?"><a href="#1-为什么需要UTXO集合?" class="headerlink" title="1. 为什么需要UTXO集合?"></a>1. 为什么需要UTXO集合?</h3><p>传统方式下,查找未花费输出需要遍历整个区块链,这种方式效率低下。通过引入UTXO集合,我们可以直接查询当前所有未花费输出,大大提高效率。<br><img src="https://cdn-a.markji.com/files/6822f53ffae6898c0c26ffba_hd.png?e=1747153874484&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:c2Ro2_JRUcMxSSnArHqak3YBN28=" alt="图片1"></p><h3 id="2-UTXO集合实现"><a href="#2-UTXO集合实现" class="headerlink" title="2. UTXO集合实现"></a>2. UTXO集合实现</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// UTXO集合结构体</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">struct</span> <span class="title class_">UTXOSet</span> {</span><br><span class="line"> blockchain: Blockchain,</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">UTXOSet</span> {</span><br><span class="line"> <span class="comment">// 重建UTXO集合</span></span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">reindex</span>(&<span class="keyword">self</span>) <span class="punctuation">-></span> <span class="type">Result</span><()> {</span><br><span class="line"> <span class="comment">// 清空当前bucket</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">db</span> = <span class="keyword">self</span>.blockchain.db.<span class="title function_ invoke__">clone</span>();</span><br><span class="line"> db.<span class="title function_ invoke__">drop_bucket</span>(UTXO_BUCKET)?;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 获取所有UTXO</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">utxos</span> = <span class="keyword">self</span>.blockchain.<span class="title function_ invoke__">find_all_utxo</span>()?;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 存储到新的bucket</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">bucket</span> = db.<span class="title function_ invoke__">create_bucket</span>(UTXO_BUCKET)?;</span><br><span class="line"> <span class="keyword">for</span> (txid, outs) <span class="keyword">in</span> utxos {</span><br><span class="line"> bucket.<span class="title function_ invoke__">put</span>(txid, <span class="title function_ invoke__">serialize</span>(&outs)?)?;</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 更新UTXO集合</span></span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">update</span>(&<span class="keyword">self</span>, block: &Block) <span class="punctuation">-></span> <span class="type">Result</span><()> {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">db</span> = <span class="keyword">self</span>.blockchain.db.<span class="title function_ invoke__">clone</span>();</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">bucket</span> = db.<span class="title function_ invoke__">get_bucket</span>(UTXO_BUCKET)?;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 处理新块中的交易</span></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">tx</span> <span class="keyword">in</span> &block.transactions {</span><br><span class="line"> <span class="comment">// 删除已花费输出</span></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">input</span> <span class="keyword">in</span> &tx.vin {</span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">outs</span> = deserialize::<TXOutputs>(&bucket.<span class="title function_ invoke__">get</span>(&input.txid)?)?;</span><br><span class="line"> outs.outputs.<span class="title function_ invoke__">remove</span>(input.vout <span class="keyword">as</span> <span class="type">usize</span>);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> outs.outputs.<span class="title function_ invoke__">is_empty</span>() {</span><br><span class="line"> bucket.<span class="title function_ invoke__">delete</span>(&input.txid)?;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> bucket.<span class="title function_ invoke__">put</span>(&input.txid, <span class="title function_ invoke__">serialize</span>(&outs)?)?;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 添加新的未花费输出</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">new_outputs</span> = TXOutputs { outputs: <span class="built_in">vec!</span>[] };</span><br><span class="line"> <span class="keyword">for</span> <span class="variable">output</span> <span class="keyword">in</span> &tx.vout {</span><br><span class="line"> new_outputs.outputs.<span class="title function_ invoke__">push</span>(output.<span class="title function_ invoke__">clone</span>());</span><br><span class="line"> }</span><br><span class="line"> bucket.<span class="title function_ invoke__">put</span>(&tx.id, <span class="title function_ invoke__">serialize</span>(&new_outputs)?)?;</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Merkle树实现"><a href="#Merkle树实现" class="headerlink" title="Merkle树实现"></a>Merkle树实现</h2><p><img src="https://cdn-a.markji.com/files/6822f8b22220c11a3674f080_hd.png?e=1747153874484&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:OfU55_MSwwx1dU654mki3gzdSuU=" alt="图片1"></p><h3 id="1-Merkle树的作用"><a href="#1-Merkle树的作用" class="headerlink" title="1. Merkle树的作用"></a>1. Merkle树的作用</h3><p>Merkle树允许轻节点(SPV节点)在不下载整个区块的情况下验证交易,只需要:</p><ul><li>交易哈希</li><li>Merkle树根哈希</li><li>Merkle路径</li></ul><h3 id="2-数据结构"><a href="#2-数据结构" class="headerlink" title="2. 数据结构"></a>2. 数据结构</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Merkle树节点</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">struct</span> <span class="title class_">MerkleNode</span> {</span><br><span class="line"> left: <span class="type">Option</span><<span class="type">Box</span><MerkleNode>>,</span><br><span class="line"> right: <span class="type">Option</span><<span class="type">Box</span><MerkleNode>>,</span><br><span class="line"> data: <span class="type">Vec</span><<span class="type">u8</span>>,</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// Merkle树</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">struct</span> <span class="title class_">MerkleTree</span> {</span><br><span class="line"> root: <span class="type">Option</span><MerkleNode>,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-核心实现"><a href="#3-核心实现" class="headerlink" title="3. 核心实现"></a>3. 核心实现</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">impl</span> <span class="title class_">MerkleNode</span> {</span><br><span class="line"> <span class="comment">// 创建新节点</span></span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">new</span>(left: <span class="type">Option</span><MerkleNode>, right: <span class="type">Option</span><MerkleNode>, data: <span class="type">Vec</span><<span class="type">u8</span>>) <span class="punctuation">-></span> <span class="keyword">Self</span> {</span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">combined</span> = <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> combined.<span class="title function_ invoke__">extend</span>(&data);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">let</span> <span class="variable">Some</span>(left) = &left {</span><br><span class="line"> combined.<span class="title function_ invoke__">extend</span>(&left.data);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">let</span> <span class="variable">Some</span>(right) = &right {</span><br><span class="line"> combined.<span class="title function_ invoke__">extend</span>(&right.data);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> <span class="variable">hash</span> = crypto::<span class="title function_ invoke__">sha256</span>(&combined);</span><br><span class="line"> </span><br><span class="line"> MerkleNode {</span><br><span class="line"> left: left.<span class="title function_ invoke__">map</span>(<span class="type">Box</span>::new),</span><br><span class="line"> right: right.<span class="title function_ invoke__">map</span>(<span class="type">Box</span>::new),</span><br><span class="line"> data: hash,</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">MerkleTree</span> {</span><br><span class="line"> <span class="comment">// 构建Merkle树</span></span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">new</span>(data: <span class="type">Vec</span><<span class="type">Vec</span><<span class="type">u8</span>>>) <span class="punctuation">-></span> <span class="keyword">Self</span> {</span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">nodes</span> = <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 创建叶子节点</span></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">d</span> <span class="keyword">in</span> data {</span><br><span class="line"> nodes.<span class="title function_ invoke__">push</span>(MerkleNode::<span class="title function_ invoke__">new</span>(<span class="literal">None</span>, <span class="literal">None</span>, d));</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 构建树</span></span><br><span class="line"> <span class="keyword">while</span> nodes.<span class="title function_ invoke__">len</span>() > <span class="number">1</span> {</span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">new_level</span> = <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> <span class="variable">i</span> <span class="keyword">in</span> (<span class="number">0</span>..nodes.<span class="title function_ invoke__">len</span>()).<span class="title function_ invoke__">step_by</span>(<span class="number">2</span>) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">left</span> = nodes[i].<span class="title function_ invoke__">clone</span>();</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">right</span> = <span class="keyword">if</span> i + <span class="number">1</span> < nodes.<span class="title function_ invoke__">len</span>() {</span><br><span class="line"> nodes[i + <span class="number">1</span>].<span class="title function_ invoke__">clone</span>()</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> nodes[i].<span class="title function_ invoke__">clone</span>()</span><br><span class="line"> };</span><br><span class="line"> </span><br><span class="line"> new_level.<span class="title function_ invoke__">push</span>(MerkleNode::<span class="title function_ invoke__">new</span>(</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(left),</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(right),</span><br><span class="line"> <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>(),</span><br><span class="line"> ));</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> nodes = new_level;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> MerkleTree {</span><br><span class="line"> root: <span class="keyword">if</span> nodes.<span class="title function_ invoke__">is_empty</span>() {</span><br><span class="line"> <span class="literal">None</span></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(nodes.<span class="title function_ invoke__">remove</span>(<span class="number">0</span>))</span><br><span class="line"> },</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="4-区块哈希计算优化"><a href="#4-区块哈希计算优化" class="headerlink" title="4. 区块哈希计算优化"></a>4. 区块哈希计算优化</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">impl</span> <span class="title class_">Block</span> {</span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">hash</span>(&<span class="keyword">self</span>) <span class="punctuation">-></span> <span class="type">Vec</span><<span class="type">u8</span>> {</span><br><span class="line"> <span class="comment">// 构建交易的Merkle树</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">txs_data</span>: <span class="type">Vec</span><<span class="type">Vec</span><<span class="type">u8</span>>> = <span class="keyword">self</span>.transactions</span><br><span class="line"> .<span class="title function_ invoke__">iter</span>()</span><br><span class="line"> .<span class="title function_ invoke__">map</span>(|tx| tx.<span class="title function_ invoke__">hash</span>())</span><br><span class="line"> .<span class="title function_ invoke__">collect</span>();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">let</span> <span class="variable">tree</span> = MerkleTree::<span class="title function_ invoke__">new</span>(txs_data);</span><br><span class="line"> tree.root.<span class="title function_ invoke__">unwrap</span>().data</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">详细介绍比特币交易系统的升级实现,包括UTXO集合的管理和Merkle树的构建过程</summary>
<category term="区块链开发" scheme="https://eatbreads.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE%E5%BC%80%E5%8F%91/"/>
<category term="区块链" scheme="https://eatbreads.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
<category term="Rust" scheme="https://eatbreads.github.io/tags/Rust/"/>
<category term="比特币" scheme="https://eatbreads.github.io/tags/%E6%AF%94%E7%89%B9%E5%B8%81/"/>
</entry>
<entry>
<title>Wireshark抓包实战分析</title>
<link href="https://eatbreads.github.io/posts/fe209838.html"/>
<id>https://eatbreads.github.io/posts/fe209838.html</id>
<published>2025-05-12T15:51:23.000Z</published>
<updated>2025-05-13T15:51:33.881Z</updated>
<content type="html"><![CDATA[<h1 id="Wireshark抓包实战分析"><a href="#Wireshark抓包实战分析" class="headerlink" title="Wireshark抓包实战分析"></a>Wireshark抓包实战分析</h1><h2 id="ARP协议分析"><a href="#ARP协议分析" class="headerlink" title="ARP协议分析"></a>ARP协议分析</h2><p>ARP(地址解析协议)用于将IP地址解析为MAC地址。通过Wireshark可以清晰地观察整个ARP请求和响应过程。</p><p><img src="https://cdn-a.markji.com/files/6821acd4e67106b1a989b5ef_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:5dem2mcOVAoMnhTUyZnHPtAPnng=" alt="图片1"></p><h3 id="ARP请求-响应分析"><a href="#ARP请求-响应分析" class="headerlink" title="ARP请求/响应分析"></a>ARP请求/响应分析</h3><ol><li>ARP请求广播</li><li>目标主机响应</li><li>MAC地址缓存</li></ol><h2 id="DNS协议分析"><a href="#DNS协议分析" class="headerlink" title="DNS协议分析"></a>DNS协议分析</h2><p>DNS查询过程展示了域名如何被解析为IP地址。为了安全考虑,建议配置HTTPS来防止DNS劫持。</p><p><img src="https://cdn-a.markji.com/files/6821ad90e67106b1a989d491_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:34DkpmluEwv7YEsfYDyd9C50keU=" alt="图片1"></p><h3 id="DNS安全配置"><a href="#DNS安全配置" class="headerlink" title="DNS安全配置"></a>DNS安全配置</h3><ol><li>使用加密DNS</li><li>配置HTTPS</li><li>防止DNS劫持</li></ol><h2 id="HTTP协议分析"><a href="#HTTP协议分析" class="headerlink" title="HTTP协议分析"></a>HTTP协议分析</h2><p>通过Wireshark可以完整地观察一次HTTP请求的全过程,包括:</p><p><img src="https://cdn-a.markji.com/files/6821add62d05657363d1dda0_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:4PWw6FUKqfCWgeXEe0737YRUWh0=" alt="图片1"></p><p><img src="https://cdn-a.markji.com/files/6821c057e67106b1a98c5d42_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:qPRSAnDi4pWgI5mHsv2qXLQOxT8=" alt="图片1"></p>]]></content>
<summary type="html">使用Wireshark进行ARP、DNS和HTTP协议的抓包分析实战</summary>
<category term="网络安全" scheme="https://eatbreads.github.io/categories/%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8/"/>
<category term="Wireshark" scheme="https://eatbreads.github.io/tags/Wireshark/"/>
<category term="网络分析" scheme="https://eatbreads.github.io/tags/%E7%BD%91%E7%BB%9C%E5%88%86%E6%9E%90/"/>
<category term="安全" scheme="https://eatbreads.github.io/tags/%E5%AE%89%E5%85%A8/"/>
</entry>
<entry>
<title>Wireshark基础使用指南</title>
<link href="https://eatbreads.github.io/posts/5c6d8554.html"/>
<id>https://eatbreads.github.io/posts/5c6d8554.html</id>
<published>2025-05-12T15:47:26.000Z</published>
<updated>2025-05-12T15:50:12.775Z</updated>
<content type="html"><![CDATA[<h1 id="Wireshark基础使用指南"><a href="#Wireshark基础使用指南" class="headerlink" title="Wireshark基础使用指南"></a>Wireshark基础使用指南</h1><h2 id="抓包设置"><a href="#抓包设置" class="headerlink" title="抓包设置"></a>抓包设置</h2><h3 id="选择网络接口"><a href="#选择网络接口" class="headerlink" title="选择网络接口"></a>选择网络接口</h3><ol><li>打开菜单栏 <code>Capture -> Option</code></li><li>选择需要监听的网络接口(通常是WLAN)</li><li>点击开始捕获<br><img src="https://cdn-a.markji.com/files/682195012d05657363ced73b_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:RLpXwtfdryDBfAHCTal-s1GxD5Y=" alt="图片1"><h2 id="数据包分析"><a href="#数据包分析" class="headerlink" title="数据包分析"></a>数据包分析</h2></li></ol><h3 id="1-分层结构"><a href="#1-分层结构" class="headerlink" title="1. 分层结构"></a>1. 分层结构</h3><p>Wireshark显示的数据包遵循OSI七层模型:</p><ul><li>物理层</li><li>数据链路层</li><li>网络层</li><li>传输层</li><li>会话层</li><li>表示层</li><li>应用层</li></ul><h3 id="2-数据显示"><a href="#2-数据显示" class="headerlink" title="2. 数据显示"></a>2. 数据显示</h3><p>每个数据包都有两种显示方式:</p><ul><li>分层协议详情</li><li>16进制原始数据</li></ul><h2 id="过滤器使用"><a href="#过滤器使用" class="headerlink" title="过滤器使用"></a>过滤器使用</h2><p>Wireshark提供两种类型的过滤器:</p><h3 id="1-捕获过滤器"><a href="#1-捕获过滤器" class="headerlink" title="1. 捕获过滤器"></a>1. 捕获过滤器</h3><ul><li>在开始捕获前设置</li><li>只捕获符合条件的数据包</li><li>减少系统资源占用</li><li>适合长时间抓包</li></ul><h3 id="2-显示过滤器"><a href="#2-显示过滤器" class="headerlink" title="2. 显示过滤器"></a>2. 显示过滤器</h3><ul><li>对已捕获的数据包进行过滤</li><li>不影响捕获过程</li><li>可以随时修改过滤条件</li><li>更灵活的过滤语法</li></ul><h2 id="常用过滤语法"><a href="#常用过滤语法" class="headerlink" title="常用过滤语法"></a>常用过滤语法</h2><h3 id="1-IP地址过滤"><a href="#1-IP地址过滤" class="headerlink" title="1. IP地址过滤"></a>1. IP地址过滤</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 精确匹配</span><br><span class="line">ip.addr == 192.168.1.1</span><br><span class="line"></span><br><span class="line"># 模糊匹配</span><br><span class="line">ip.addr contains 192.168</span><br></pre></td></tr></table></figure><h3 id="2-协议过滤"><a href="#2-协议过滤" class="headerlink" title="2. 协议过滤"></a>2. 协议过滤</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 单一协议</span><br><span class="line">http</span><br><span class="line"></span><br><span class="line"># 多协议组合</span><br><span class="line">http or https</span><br></pre></td></tr></table></figure><h3 id="3-端口过滤"><a href="#3-端口过滤" class="headerlink" title="3. 端口过滤"></a>3. 端口过滤</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 精确匹配</span><br><span class="line">tcp.port == 80</span><br><span class="line"></span><br><span class="line"># 源端口</span><br><span class="line">tcp.srcport == 80</span><br><span class="line"></span><br><span class="line"># 目标端口</span><br><span class="line">tcp.dstport == 80</span><br></pre></td></tr></table></figure><h3 id="4-组合过滤"><a href="#4-组合过滤" class="headerlink" title="4. 组合过滤"></a>4. 组合过滤</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># IP + 协议 + 端口</span><br><span class="line">ip.addr == 192.168.1.1 and http and tcp.port == 80</span><br><span class="line"></span><br><span class="line"># 多条件模糊匹配</span><br><span class="line">ip.addr contains 192.168 and tcp.port contains 80</span><br></pre></td></tr></table></figure><p><img src="https://cdn-a.markji.com/files/6821a908e67106b1a9894208_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:tGkfkJXjoSGZV175f6j50AysSOs=" alt="图片1"><br><img src="https://cdn-a.markji.com/files/6821ab572d05657363d18ed8_hd.png?e=1747062464240&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:y2irddxsCry90fqf5pfHmUof9PM=" alt="图片1"></p><h2 id="过滤器使用技巧"><a href="#过滤器使用技巧" class="headerlink" title="过滤器使用技巧"></a>过滤器使用技巧</h2><ol><li><p><strong>运算符</strong></p><ul><li><code>==</code> 精确匹配</li><li><code>contains</code> 包含匹配</li><li><code>and</code> 与</li><li><code>or</code> 或</li><li><code>not</code> 非</li></ul></li><li><p><strong>常用组合</strong></p><ul><li>特定IP的HTTP流量:<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ip.addr == 192.168.1.1 and http</span><br></pre></td></tr></table></figure></li><li>特定端口的TCP流量:<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tcp.port == 443 and tcp</span><br></pre></td></tr></table></figure></li></ul></li><li><p><strong>保存过滤器</strong></p><ul><li>可以保存常用的过滤器表达式</li><li>方便快速切换不同的过滤条件</li></ul></li></ol>]]></content>
<summary type="html">详细介绍Wireshark的基本使用方法,包括抓包设置、数据包分析和过滤器使用</summary>
<category term="网络工具" scheme="https://eatbreads.github.io/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E5%85%B7/"/>
<category term="Wireshark" scheme="https://eatbreads.github.io/tags/Wireshark/"/>
<category term="网络分析" scheme="https://eatbreads.github.io/tags/%E7%BD%91%E7%BB%9C%E5%88%86%E6%9E%90/"/>
<category term="抓包工具" scheme="https://eatbreads.github.io/tags/%E6%8A%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
</entry>
<entry>
<title>Nginx基础配置与使用指南</title>
<link href="https://eatbreads.github.io/posts/8a38e9a9.html"/>
<id>https://eatbreads.github.io/posts/8a38e9a9.html</id>
<published>2025-05-03T14:59:43.000Z</published>
<updated>2025-05-03T15:03:12.762Z</updated>
<content type="html"><![CDATA[<h3 id="虽然是很久以前做的了-但是还是记录一下吧-因为五一没学习没东西更新博客了-嘻嘻">虽然是很久以前做的了,但是还是记录一下吧,因为五一没学习没东西更新博客了(嘻嘻)</h3><h1>Nginx基础配置与使用指南</h1><h2 id="Nginx简介">Nginx简介</h2><p>Nginx是一款轻量级的Web服务器和反向代理服务器,以其高性能、稳定性和低资源消耗而闻名。它可以作为HTTP服务器,也可以作为反向代理服务器,支持负载均衡等高级功能。</p><h2 id="基本命令">基本命令</h2><h3 id="1-服务管理">1. 服务管理</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动服务</span></span><br><span class="line">/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭服务</span></span><br><span class="line">/usr/local/nginx/sbin/nginx -s stop</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启服务</span></span><br><span class="line">/usr/local/nginx/sbin/nginx -s reload</span><br><span class="line"></span><br><span class="line"><span class="comment"># 优雅退出</span></span><br><span class="line">/usr/local/nginx/sbin/nginx -s quit</span><br></pre></td></tr></table></figure><h3 id="2-配置文件管理">2. 配置文件管理</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 编辑主配置文件</span></span><br><span class="line">vim /usr/local/nginx/conf/nginx.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看错误日志</span></span><br><span class="line"><span class="built_in">tail</span> -f /usr/local/nginx/logs/error.log</span><br></pre></td></tr></table></figure><h2 id="配置详解">配置详解</h2><h3 id="1-基础配置结构">1. 基础配置结构</h3><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 主配置文件</span></span><br><span class="line"><span class="section">http</span> {</span><br><span class="line"> <span class="attribute">include</span> mime.types;</span><br><span class="line"> <span class="attribute">default_type</span> application/octet-stream;</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 包含其他配置文件</span></span><br><span class="line"> <span class="attribute">include</span> /usr/local/nginx/conf/conf.d/<span class="regexp">*.conf</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="2-站点配置示例">2. 站点配置示例</h3><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> {</span><br><span class="line"> <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line"> <span class="attribute">server_name</span> example.com;</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 网站根目录</span></span><br><span class="line"> <span class="attribute">root</span> /var/www/html;</span><br><span class="line"> </span><br><span class="line"> <span class="comment"># 默认首页</span></span><br><span class="line"> <span class="attribute">index</span> index.html index.htm;</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 路径配置</span></span><br><span class="line"> <span class="section">location</span> /admin {</span><br><span class="line"> <span class="attribute">root</span> /var/www/admin;</span><br><span class="line"> <span class="attribute">index</span> index.html;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-反向代理配置">3. 反向代理配置</h3><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">location</span> /api {</span><br><span class="line"> <span class="attribute">proxy_pass</span> http://backend-server;</span><br><span class="line"> <span class="attribute">proxy_set_header</span> Host <span class="variable">$host</span>;</span><br><span class="line"> <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="常见操作流程">常见操作流程</h2><h3 id="1-添加新站点">1. 添加新站点</h3><ol><li>创建配置文件</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /usr/local/nginx/conf/conf.d/mysite.conf</span><br></pre></td></tr></table></figure><ol start="2"><li>编写配置内容</li></ol><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> {</span><br><span class="line"> <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line"> <span class="attribute">server_name</span> mysite.com;</span><br><span class="line"> <span class="attribute">root</span> /var/www/mysite;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="3"><li>重新加载配置</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/nginx/sbin/nginx -s reload</span><br></pre></td></tr></table></figure><h3 id="2-故障排查">2. 故障排查</h3><ol><li>检查配置语法</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/nginx/sbin/nginx -t</span><br></pre></td></tr></table></figure><ol start="2"><li>查看错误日志</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">tail</span> -f /usr/local/nginx/logs/error.log</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">记录Nginx的基本使用方法,包括服务管理、配置修改和反向代理设置</summary>
<category term="运维笔记" scheme="https://eatbreads.github.io/categories/%E8%BF%90%E7%BB%B4%E7%AC%94%E8%AE%B0/"/>
<category term="服务器" scheme="https://eatbreads.github.io/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
<category term="运维" scheme="https://eatbreads.github.io/tags/%E8%BF%90%E7%BB%B4/"/>
<category term="Nginx" scheme="https://eatbreads.github.io/tags/Nginx/"/>
</entry>
<entry>
<title>区块链钱包地址生成原理</title>
<link href="https://eatbreads.github.io/posts/fcfcdc9e.html"/>
<id>https://eatbreads.github.io/posts/fcfcdc9e.html</id>
<published>2025-05-02T13:22:27.000Z</published>
<updated>2025-05-02T13:25:52.995Z</updated>
<content type="html"><![CDATA[<h1>区块链钱包地址生成原理</h1><h2 id="地址生成流程图">地址生成流程图</h2><p><img src="https://cdn-a.markji.com/files/6814c7319209d5011496b4fd_hd.png?e=1746194770056&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:P1YSyOXLmo8LmVfo4AY8uqr87AA=" alt="钱包地址生成流程"></p><h2 id="实现步骤">实现步骤</h2><h3 id="1-生成随机数">1. 生成随机数</h3><p>首先需要生成一个高质量的随机数作为种子:</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> rand::OsRng;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用操作系统级别的随机数生成器</span></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">rand</span> = rand::OsRng::<span class="title function_ invoke__">new</span>().<span class="title function_ invoke__">unwrap</span>();</span><br></pre></td></tr></table></figure><p>这里使用了操作系统提供的随机数生成器,可以保证随机数的安全性和随机性。</p><h3 id="2-生成密钥对">2. 生成密钥对</h3><p>使用Ed25519椭圆曲线算法生成公私钥对:</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> ed25519_dalek::{Keypair, PublicKey, SecretKey};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 生成密钥对</span></span><br><span class="line"><span class="keyword">let</span> (secret_key, public_key) = ed25519::<span class="title function_ invoke__">keypair</span>(&key);</span><br></pre></td></tr></table></figure><p>Ed25519是一种高效安全的椭圆曲线算法,广泛应用于区块链和加密货币领域。</p><h3 id="3-公钥哈希化">3. 公钥哈希化</h3><p>对公钥进行SHA256哈希运算:</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> sha2::{Sha256, Digest};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建SHA256哈希器</span></span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">hasher1</span> = Sha256::<span class="title function_ invoke__">new</span>();</span><br><span class="line"><span class="comment">// 输入公钥数据</span></span><br><span class="line">hasher1.<span class="title function_ invoke__">input</span>(pubKey);</span><br><span class="line"><span class="comment">// 获取哈希结果</span></span><br><span class="line">hasher1.<span class="title function_ invoke__">result</span>(pubKey);</span><br></pre></td></tr></table></figure><p>哈希化可以:</p><ul><li>缩短地址长度</li><li>提高安全性</li><li>增加地址的唯一性</li></ul><h3 id="4-Base58编码">4. Base58编码</h3><p>将哈希后的公钥转换为人类可读的格式:</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建地址结构</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">address</span> = Address {</span><br><span class="line"> body: pub_hash,</span><br><span class="line"> scheme: Scheme::Base58, <span class="comment">// 使用Base58编码</span></span><br><span class="line"> hash_type: HashType::Script,</span><br><span class="line"> ..<span class="built_in">Default</span>::<span class="title function_ invoke__">default</span>()</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">// 进行编码</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">readable_address</span> = address.<span class="title function_ invoke__">encode</span>().<span class="title function_ invoke__">unwrap</span>();</span><br></pre></td></tr></table></figure><p>Base58编码的特点:</p><ul><li>避免使用容易混淆的字符</li><li>保持较高的信息密度</li><li>便于人工识别和输入</li></ul><h2 id="安全考虑">安全考虑</h2><ol><li><p><strong>随机数生成</strong></p><ul><li>使用密码学安全的随机数生成器</li><li>避免使用伪随机数</li><li>确保熵值充足</li></ul></li><li><p><strong>私钥保护</strong></p><ul><li>永远不在网络传输私钥</li><li>使用安全的存储方式</li><li>考虑多重签名机制</li></ul></li><li><p><strong>地址校验</strong></p><ul><li>添加校验和</li><li>验证地址格式</li><li>防止输入错误</li></ul></li></ol><h2 id="最佳实践">最佳实践</h2><ol><li><strong>密钥管理</strong></li></ol><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 安全存储私钥</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">encrypted_key</span> = <span class="title function_ invoke__">encrypt_key</span>(&secret_key, password);</span><br><span class="line"><span class="title function_ invoke__">save_to_keystore</span>(&encrypted_key);</span><br></pre></td></tr></table></figure><ol start="2"><li><strong>地址验证</strong></li></ol><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 验证地址有效性</span></span><br><span class="line"><span class="keyword">if</span> !address.<span class="title function_ invoke__">is_valid</span>() {</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">Err</span>(<span class="string">"Invalid address format"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol start="3"><li><strong>错误处理</strong></li></ol><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 完善的错误处理</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">address</span> = <span class="keyword">match</span> Address::<span class="title function_ invoke__">new</span>(pub_hash) {</span><br><span class="line"> <span class="title function_ invoke__">Ok</span>(addr) => addr,</span><br><span class="line"> <span class="title function_ invoke__">Err</span>(e) => <span class="title function_ invoke__">handle_error</span>(e),</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">详细介绍区块链钱包地址的生成过程,包括随机数生成、密钥对创建和地址编码</summary>
<category term="区块链开发" scheme="https://eatbreads.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE%E5%BC%80%E5%8F%91/"/>
<category term="区块链" scheme="https://eatbreads.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
<category term="Rust" scheme="https://eatbreads.github.io/tags/Rust/"/>
<category term="加密算法" scheme="https://eatbreads.github.io/tags/%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95/"/>
</entry>
<entry>
<title>区块链网络通信流程详解</title>
<link href="https://eatbreads.github.io/posts/a56f3323.html"/>
<id>https://eatbreads.github.io/posts/a56f3323.html</id>
<published>2025-05-01T13:02:30.000Z</published>
<updated>2025-05-01T13:06:32.072Z</updated>
<content type="html"><![CDATA[<h1 id="区块链网络通信流程详解"><a href="#区块链网络通信流程详解" class="headerlink" title="区块链网络通信流程详解"></a>区块链网络通信流程详解</h1><h2 id="网络通信流程图"><a href="#网络通信流程图" class="headerlink" title="网络通信流程图"></a>网络通信流程图</h2><p><img src="https://cdn-a.markji.com/files/681371c72d056573630e9f46_hd.png?e=1746107367582&token=xX63b9jqTlDOcGmctt5K9254rV0LG8hS9BmDeFBy:_6gQHn20mgVSAAOWAXrxm_fAnf4=" alt="区块链网络通信流程"></p><h2 id="接收方流程"><a href="#接收方流程" class="headerlink" title="接收方流程"></a>接收方流程</h2><h3 id="1-启动服务"><a href="#1-启动服务" class="headerlink" title="1. 启动服务"></a>1. 启动服务</h3><ul><li>调用 <code>startServer</code></li><li>开始监听网络连接</li><li>准备接收其他节点的请求</li></ul><h3 id="2-版本处理-handleVersion"><a href="#2-版本处理-handleVersion" class="headerlink" title="2. 版本处理 (handleVersion)"></a>2. 版本处理 (handleVersion)</h3><ul><li>接收版本信息</li><li>比较区块高度<ul><li>如果自身区块链较短:请求获取新块</li><li>如果自身区块链较长:发送version给对方</li></ul></li><li>注意:发送version是发起同步请求的方式</li></ul><h3 id="3-清单处理-handleInv"><a href="#3-清单处理-handleInv" class="headerlink" title="3. 清单处理 (handleInv)"></a>3. 清单处理 (handleInv)</h3><ul><li>接收发送方的Inv清单<ul><li>包含块信息和交易信息</li></ul></li><li>分析清单内容<ul><li>确定需要下载的内容</li></ul></li><li>调用getData执行实际下载</li></ul><h3 id="4-区块处理-handleBlock"><a href="#4-区块处理-handleBlock" class="headerlink" title="4. 区块处理 (handleBlock)"></a>4. 区块处理 (handleBlock)</h3><ul><li>接收新区块</li><li>验证区块有效性</li><li>将新区块添加到本地链中</li><li>更新区块链状态</li></ul><h3 id="5-交易处理-handleTx"><a href="#5-交易处理-handleTx" class="headerlink" title="5. 交易处理 (handleTx)"></a>5. 交易处理 (handleTx)</h3><ul><li>接收新交易</li><li>验证交易有效性</li><li>将交易加入内存池</li><li>准备打包新区块</li></ul><h2 id="发送方流程"><a href="#发送方流程" class="headerlink" title="发送方流程"></a>发送方流程</h2><h3 id="1-服务启动"><a href="#1-服务启动" class="headerlink" title="1. 服务启动"></a>1. 服务启动</h3><ul><li>调用 <code>startServer</code></li><li>初始化网络服务</li><li>准备响应请求</li></ul><h3 id="2-区块获取请求处理-handleGetBlock"><a href="#2-区块获取请求处理-handleGetBlock" class="headerlink" title="2. 区块获取请求处理 (handleGetBlock)"></a>2. 区块获取请求处理 (handleGetBlock)</h3><ul><li>接收获取区块请求</li><li>查找请求的区块</li><li>准备区块数据</li><li>发送区块信息</li></ul><h3 id="3-数据请求处理-getData"><a href="#3-数据请求处理-getData" class="headerlink" title="3. 数据请求处理 (getData)"></a>3. 数据请求处理 (getData)</h3><ul><li>接收具体数据请求</li><li>根据请求类型处理<ul><li>区块请求:返回完整区块</li><li>交易请求:返回交易详情</li></ul></li><li>发送请求的数据</li></ul><h2 id="通信要点"><a href="#通信要点" class="headerlink" title="通信要点"></a>通信要点</h2><ol><li><p><strong>版本同步机制</strong></p><ul><li>通过version消息进行区块链状态同步</li><li>确保节点间数据一致性</li></ul></li><li><p><strong>数据传输流程</strong></p><ul><li>Inv清单作为数据索引</li><li>getData请求具体数据</li><li>分块传输避免网络拥堵</li></ul></li><li><p><strong>状态维护</strong></p><ul><li>跟踪待下载的区块</li><li>管理交易内存池</li><li>维护节点连接状态</li></ul></li><li><p><strong>错误处理</strong></p><ul><li>网络断开重连</li><li>数据验证失败处理</li><li>超时重试机制</li></ul></li></ol><p>通过这种设计,我们实现了一个可靠的P2P网络通信机制,确保了区块链网络的正常运行和数据同步。</p>]]></content>
<summary type="html">详细介绍区块链P2P网络中节点间的通信流程</summary>
<category term="区块链开发" scheme="https://eatbreads.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE%E5%BC%80%E5%8F%91/"/>
<category term="区块链" scheme="https://eatbreads.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
<category term="网络通信" scheme="https://eatbreads.github.io/tags/%E7%BD%91%E7%BB%9C%E9%80%9A%E4%BF%A1/"/>
<category term="流程图" scheme="https://eatbreads.github.io/tags/%E6%B5%81%E7%A8%8B%E5%9B%BE/"/>
</entry>
<entry>
<title>区块链网络部分实现</title>
<link href="https://eatbreads.github.io/posts/5a225ca.html"/>
<id>https://eatbreads.github.io/posts/5a225ca.html</id>
<published>2025-04-30T15:32:26.000Z</published>
<updated>2025-04-30T15:36:27.225Z</updated>
<content type="html"><![CDATA[<h1>区块链网络实现详解</h1><h2 id="网络架构">网络架构</h2><p>区块链网络采用P2P(点对点)拓扑扁平结构,每个节点同时具备服务器和客户端的双重身份。这种去中心化的架构确保了网络的健壮性和可扩展性。</p><h3 id="节点类型">节点类型</h3><ol><li><p><strong>矿工节点</strong></p><ul><li>负责打包交易</li><li>进行工作量证明</li><li>广播新区块</li></ul></li><li><p><strong>全节点</strong></p><ul><li>存储完整的区块链数据</li><li>提供网络路由功能</li><li>验证交易和区块</li></ul></li><li><p><strong>SPV节点</strong>(简单支付验证)</p><ul><li>只存储区块头</li><li>维护特定交易子集</li><li>轻量级客户端实现</li></ul></li></ol><h2 id="网络通信流程">网络通信流程</h2><h3 id="1-版本验证">1. 版本验证</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Version消息结构</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Version</span> {</span><br><span class="line"> version: <span class="type">i32</span>,</span><br><span class="line"> best_height: <span class="type">i32</span>,</span><br><span class="line"> addr_from: <span class="type">String</span>,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="2-区块同步">2. 区块同步</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// GetBlocks消息结构</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">GetBlocks</span> {</span><br><span class="line"> addr_from: <span class="type">String</span>,</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// Inv消息结构</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Inv</span> {</span><br><span class="line"> addr_from: <span class="type">String</span>,</span><br><span class="line"> type_: <span class="type">String</span>, <span class="comment">// "block" 或 "tx"</span></span><br><span class="line"> items: <span class="type">Vec</span><<span class="type">String</span>>,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-数据请求">3. 数据请求</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// GetData消息结构</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">GetData</span> {</span><br><span class="line"> addr_from: <span class="type">String</span>,</span><br><span class="line"> type_: <span class="type">String</span>,</span><br><span class="line"> id: <span class="type">String</span>,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="核心组件实现">核心组件实现</h2><h3 id="1-服务器启动">1. 服务器启动</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">start_server</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">listener</span> = TcpListener::<span class="title function_ invoke__">bind</span>(&<span class="keyword">self</span>.node_addr)?;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 非中心节点需要同步</span></span><br><span class="line"> <span class="keyword">if</span> !<span class="keyword">self</span>.is_central_node {</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">send_version</span>(CENTRAL_NODE_ADDR);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 主循环处理连接</span></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">stream</span> <span class="keyword">in</span> listener.<span class="title function_ invoke__">incoming</span>() {</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">handle_connection</span>(stream?);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="2-连接处理">2. 连接处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_connection</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, <span class="keyword">mut</span> stream: TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">command</span> = <span class="keyword">self</span>.<span class="title function_ invoke__">read_command</span>(&<span class="keyword">mut</span> stream)?;</span><br><span class="line"> <span class="keyword">match</span> command.<span class="title function_ invoke__">as_str</span>() {</span><br><span class="line"> <span class="string">"version"</span> => <span class="keyword">self</span>.<span class="title function_ invoke__">handle_version</span>(&<span class="keyword">mut</span> stream),</span><br><span class="line"> <span class="string">"getblocks"</span> => <span class="keyword">self</span>.<span class="title function_ invoke__">handle_get_blocks</span>(&<span class="keyword">mut</span> stream),</span><br><span class="line"> <span class="string">"inv"</span> => <span class="keyword">self</span>.<span class="title function_ invoke__">handle_inv</span>(&<span class="keyword">mut</span> stream),</span><br><span class="line"> <span class="string">"getdata"</span> => <span class="keyword">self</span>.<span class="title function_ invoke__">handle_get_data</span>(&<span class="keyword">mut</span> stream),</span><br><span class="line"> <span class="string">"block"</span> => <span class="keyword">self</span>.<span class="title function_ invoke__">handle_block</span>(&<span class="keyword">mut</span> stream),</span><br><span class="line"> <span class="string">"tx"</span> => <span class="keyword">self</span>.<span class="title function_ invoke__">handle_tx</span>(&<span class="keyword">mut</span> stream),</span><br><span class="line"> _ => <span class="built_in">println!</span>(<span class="string">"Unknown command"</span>),</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-版本处理">3. 版本处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_version</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, stream: &<span class="keyword">mut</span> TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">version</span>: Version = <span class="title function_ invoke__">deserialize</span>(stream)?;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 检查区块高度</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">self</span>.blockchain.<span class="title function_ invoke__">get_best_height</span>() < version.best_height {</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">send_get_blocks</span>(version.addr_from);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="4-区块请求处理">4. 区块请求处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_get_blocks</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, stream: &<span class="keyword">mut</span> TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">payload</span>: GetBlocks = <span class="title function_ invoke__">deserialize</span>(stream)?;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">blocks</span> = <span class="keyword">self</span>.blockchain.<span class="title function_ invoke__">get_block_hashes</span>();</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">send_inv</span>(payload.addr_from, <span class="string">"block"</span>, blocks);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="5-清单处理">5. 清单处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_inv</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, stream: &<span class="keyword">mut</span> TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">inv</span>: Inv = <span class="title function_ invoke__">deserialize</span>(stream)?;</span><br><span class="line"> <span class="keyword">if</span> inv.type_ == <span class="string">"block"</span> {</span><br><span class="line"> <span class="keyword">self</span>.blocks_in_transit = inv.items;</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">send_get_data</span>(inv.addr_from, <span class="string">"block"</span>, <span class="keyword">self</span>.blocks_in_transit[<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="6-数据请求处理">6. 数据请求处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_get_data</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, stream: &<span class="keyword">mut</span> TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">request</span>: GetData = <span class="title function_ invoke__">deserialize</span>(stream)?;</span><br><span class="line"> <span class="keyword">if</span> request.type_ == <span class="string">"block"</span> {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">block</span> = <span class="keyword">self</span>.blockchain.<span class="title function_ invoke__">get_block</span>(&request.id)?;</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">send_block</span>(request.addr_from, block);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="7-区块处理">7. 区块处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_block</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, stream: &<span class="keyword">mut</span> TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">block</span>: Block = <span class="title function_ invoke__">deserialize</span>(stream)?;</span><br><span class="line"> <span class="keyword">self</span>.blockchain.<span class="title function_ invoke__">add_block</span>(block)?;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 继续请求其他区块</span></span><br><span class="line"> <span class="keyword">if</span> !<span class="keyword">self</span>.blocks_in_transit.<span class="title function_ invoke__">is_empty</span>() {</span><br><span class="line"> <span class="keyword">self</span>.blocks_in_transit.<span class="title function_ invoke__">remove</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> !<span class="keyword">self</span>.blocks_in_transit.<span class="title function_ invoke__">is_empty</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">next_hash</span> = <span class="keyword">self</span>.blocks_in_transit[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">send_get_data</span>(stream.<span class="title function_ invoke__">peer_addr</span>()?, <span class="string">"block"</span>, next_hash);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="8-交易处理">8. 交易处理</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">handle_tx</span>(&<span class="keyword">mut</span> <span class="keyword">self</span>, stream: &<span class="keyword">mut</span> TcpStream) {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">tx</span>: Transaction = <span class="title function_ invoke__">deserialize</span>(stream)?;</span><br><span class="line"> <span class="keyword">self</span>.mempool.<span class="title function_ invoke__">insert</span>(tx.id.<span class="title function_ invoke__">clone</span>(), tx);</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 作为矿工节点,收集足够交易后开始挖矿</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">self</span>.is_miner && <span class="keyword">self</span>.mempool.<span class="title function_ invoke__">len</span>() >= MINING_THRESHOLD {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">txs</span>: <span class="type">Vec</span><Transaction> = <span class="keyword">self</span>.mempool.<span class="title function_ invoke__">values</span>().<span class="title function_ invoke__">cloned</span>().<span class="title function_ invoke__">collect</span>();</span><br><span class="line"> <span class="keyword">self</span>.<span class="title function_ invoke__">mine_block</span>(txs);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">详细介绍区块链P2P网络的实现原理和核心组件</summary>
<category term="区块链开发" scheme="https://eatbreads.github.io/categories/%E5%8C%BA%E5%9D%97%E9%93%BE%E5%BC%80%E5%8F%91/"/>
<category term="区块链" scheme="https://eatbreads.github.io/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/"/>
<category term="Rust" scheme="https://eatbreads.github.io/tags/Rust/"/>
<category term="P2P网络" scheme="https://eatbreads.github.io/tags/P2P%E7%BD%91%E7%BB%9C/"/>
</entry>
<entry>
<title>Python调用大模型API实战</title>
<link href="https://eatbreads.github.io/posts/ffa1ef1b.html"/>
<id>https://eatbreads.github.io/posts/ffa1ef1b.html</id>
<published>2025-04-30T15:17:28.000Z</published>
<updated>2025-04-30T15:26:00.791Z</updated>
<content type="html"><![CDATA[<h1 id="Python调用大模型API实战教程"><a href="#Python调用大模型API实战教程" class="headerlink" title="Python调用大模型API实战教程"></a>Python调用大模型API实战教程</h1><h2 id="环境准备"><a href="#环境准备" class="headerlink" title="环境准备"></a>环境准备</h2><p>首先需要安装openai库:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install openai</span><br></pre></td></tr></table></figure></p><h2 id="API申请"><a href="#API申请" class="headerlink" title="API申请"></a>API申请</h2><ol><li>访问 Deepseek 官网注册账号</li><li>在个人中心申请 API Key</li><li>获取到形如 <code>sk-0f2245****a0bb3f1e</code> 的密钥</li><li>充值以获得API调用额度</li></ol><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><h3 id="1-基础配置"><a href="#1-基础配置" class="headerlink" title="1. 基础配置"></a>1. 基础配置</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> openai <span class="keyword">import</span> OpenAI</span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建OpenAI客户端</span></span><br><span class="line">client = OpenAI(</span><br><span class="line"> api_key=<span class="string">"your-api-key"</span>, <span class="comment"># 替换为你的API密钥</span></span><br><span class="line"> base_url=<span class="string">"https://api.deepseek.com/v1"</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="2-定义Prompt模板"><a href="#2-定义Prompt模板" class="headerlink" title="2. 定义Prompt模板"></a>2. 定义Prompt模板</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">PROMPT_TEMPLATES = {</span><br><span class="line"> <span class="string">"student_info"</span>: {</span><br><span class="line"> <span class="string">"system"</span>: <span class="string">"""你是一个专注于学生基本信息分析的教育数据专家。</span></span><br><span class="line"><span class="string"> - 擅长处理学生个人信息、人口统计学特征</span></span><br><span class="line"><span class="string"> - 注重学生信息的隐私保护</span></span><br><span class="line"><span class="string"> - 专注于人口特征统计和分布分析"""</span>,</span><br><span class="line"> </span><br><span class="line"> <span class="string">"background"</span>: <span class="string">"""正在分析学生基本信息数据:</span></span><br><span class="line"><span class="string"> - 数据类型:学生个人基本信息</span></span><br><span class="line"><span class="string"> - 包含字段:学号、姓名、性别、年龄、籍贯等</span></span><br><span class="line"><span class="string"> - 分析目标:了解学生群体的基本特征分布"""</span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment"># ... 其他模板</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-数据读取函数"><a href="#3-数据读取函数" class="headerlink" title="3. 数据读取函数"></a>3. 数据读取函数</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">read_data_file</span>(<span class="params">file_path</span>):</span><br><span class="line"> <span class="string">"""读取数据文件"""</span></span><br><span class="line"> <span class="keyword">if</span> file_path.endswith(<span class="string">'.csv'</span>):</span><br><span class="line"> <span class="keyword">return</span> pd.read_csv(file_path)</span><br><span class="line"> <span class="keyword">elif</span> file_path.endswith(<span class="string">'.xlsx'</span>):</span><br><span class="line"> <span class="keyword">return</span> pd.read_excel(file_path)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">"不支持的文件格式,请使用 CSV 或 Excel 文件"</span>)</span><br></pre></td></tr></table></figure><h3 id="4-创建分析请求"><a href="#4-创建分析请求" class="headerlink" title="4. 创建分析请求"></a>4. 创建分析请求</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">create_analysis_request</span>(<span class="params">data_type, specific_task, data_file=<span class="literal">None</span></span>):</span><br><span class="line"> <span class="string">"""创建并发送分析请求"""</span></span><br><span class="line"> <span class="keyword">if</span> data_type <span class="keyword">not</span> <span class="keyword">in</span> PROMPT_TEMPLATES:</span><br><span class="line"> <span class="keyword">raise</span> ValueError(<span class="string">f"不支持的数据类型: <span class="subst">{data_type}</span>"</span>)</span><br><span class="line"> </span><br><span class="line"> template = PROMPT_TEMPLATES[data_type]</span><br><span class="line"> </span><br><span class="line"> <span class="comment"># 添加数据概览</span></span><br><span class="line"> data_overview = <span class="string">""</span></span><br><span class="line"> <span class="keyword">if</span> data_file:</span><br><span class="line"> df = read_data_file(data_file)</span><br><span class="line"> data_overview = <span class="string">f"""</span></span><br><span class="line"><span class="string"> 数据概览:</span></span><br><span class="line"><span class="string"> - 总记录数:<span class="subst">{<span class="built_in">len</span>(df)}</span></span></span><br><span class="line"><span class="string"> - 字段列表:<span class="subst">{<span class="string">', '</span>.join(df.columns)}</span></span></span><br><span class="line"><span class="string"> - 数据示例:\n<span class="subst">{df.head(<span class="number">3</span>).to_string()}</span></span></span><br><span class="line"><span class="string"> """</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment"># 发送请求</span></span><br><span class="line"> response = client.chat.completions.create(</span><br><span class="line"> model=<span class="string">"deepseek-chat"</span>,</span><br><span class="line"> messages=[</span><br><span class="line"> {<span class="string">"role"</span>: <span class="string">"system"</span>, <span class="string">"content"</span>: template[<span class="string">"system"</span>]},</span><br><span class="line"> {<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: template[<span class="string">"background"</span>] + data_overview},</span><br><span class="line"> {<span class="string">"role"</span>: <span class="string">"user"</span>, <span class="string">"content"</span>: specific_task}</span><br><span class="line"> ],</span><br><span class="line"> temperature=<span class="number">0.3</span></span><br><span class="line"> )</span><br><span class="line"> <span class="keyword">return</span> response.choices[<span class="number">0</span>].message.content</span><br></pre></td></tr></table></figure><h3 id="5-使用示例"><a href="#5-使用示例" class="headerlink" title="5. 使用示例"></a>5. 使用示例</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 定义分析任务</span></span><br><span class="line">specific_task = <span class="string">"""请分析以下内容:</span></span><br><span class="line"><span class="string">1. 数据完整性检查</span></span><br><span class="line"><span class="string">2. 主要指标的分布情况</span></span><br><span class="line"><span class="string">3. 异常值检测和处理建议</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">输出要求:</span></span><br><span class="line"><span class="string">- 格式:分点列出</span></span><br><span class="line"><span class="string">- 包含具体数值和百分比</span></span><br><span class="line"><span class="string">- 提供可视化建议"""</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行分析</span></span><br><span class="line">file_path = <span class="string">"path/to/your/data.xlsx"</span></span><br><span class="line">analysis_result = create_analysis_request(<span class="string">"student_info"</span>, specific_task, file_path)</span><br><span class="line"><span class="built_in">print</span>(analysis_result)</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">详细介绍如何使用Python调用大模型API,包括环境配置、API申请和代码实现</summary>
<category term="编程开发" scheme="https://eatbreads.github.io/categories/%E7%BC%96%E7%A8%8B%E5%BC%80%E5%8F%91/"/>
<category term="Python" scheme="https://eatbreads.github.io/tags/Python/"/>
<category term="AI" scheme="https://eatbreads.github.io/tags/AI/"/>
<category term="API调用" scheme="https://eatbreads.github.io/tags/API%E8%B0%83%E7%94%A8/"/>
</entry>
</feed>