main函数主流程(bitcoind)
    AppInit
        AppInitBasicSetup
            // ************************************ Step 1: setup注册网络及Signal
        AppInitParameterInteraction
            // ************************************ Step 2: parameter interactions 交互参数
            // ************************************ Step 3: parameter-to-internal-flags 内部参数
        AppInitSanityChecks
            // ************************************ Step 4: sanity checks 安全相关
         AppInitMain
            // ************************************ Step 4a: application initialization
                创建ScriptCheck线程, 个数为std::thread::hardware_concurrency, 不超过MAX_SCRIPTCHECK_THREADS即16个
                创建scheduler线程
                注册RPC
                创建HTTP Server 线程,提供RPC REST服务接口,1个http thread 加上多个http works(默认DEFAULT_HTTP_THREADS即4个,至少1个)
            // ************************************* Step 5: verify wallet database integrity
            // ************************************* Step 6: network initialization
            // ************************************* Step 7: load block chain
            // ************************************* Step 8: start indexers   
            // ************************************* Step 9: load wallet
            // ************************************* Step 10: data directory maintenance
            // ************************************* Step 11: import blocks
                创建import线程,加载区块数据
            // ************************************* Step 12: start node
                创建TorControl线程
                UPnP线程
                net线程
                dnsseed线程
                addcon线程: -addnode
                opencon线程: 主动向外连接
                msghand线程:消息处理
            // ************************************** Step 13: finished

从程序上看,比特币程序采用一个进程多个线程的结构,既是服务器,又是客户端。

如没有特殊说明,本系列以最新源码为准进行分析。

主要模块:
初始化
区块
交易
网络
挖矿
钱包
RPC
GUI

主要依赖:
berkeley-db
boost
level db
libevent
miniupnpc
openssl
protobuf
qrencode
qt
zmq

主要入口:

文件 函数
bitcoind.cpp main AppInit AppInitMain
bitcoin-cli.cpp main AppInitRPC CommandLineRPC CallRPC
bitcoin-tx.cpp main AppInitRawTx CommandLineRawTx MutateTx OutputTx

主要线程:

线程 作用
主线程 创建其它线程,等待interrupt
ScriptCheck 脚本检查
scheduler 执行一般任务例如定时任务
HTTP Server 提供RPC REST服务接口
import 加载区块数据
TorControl Tor线程(Optional)
UPnP UPnP线程(Optional)
net 接收连接,封装消息
dnsseed DNS地址种子解析
addcon 处理-addnode
opencon 主动向外连接
msghand 消息处理

上述线程不包括(1)db内部的线程,例如leveldb的background thread; (2)某些参数设置后会启动的线程,例如txindex参数

最近由于业务需要,写了一个 java server用来与我们的游戏服务器实现交互。

server只实现了最基本的功能: 维护多个长连接,发送与接收消息;连接建立及断开(主动与被动)。

在实现的过程中,最有意思的是java nio里的buffer,但我认为这是一个失败的设计。

java nio buffer三个主要的属性,position, limit, capacity.

通常来讲,传统的ringbuffer都会有一个read index和write index, 但buffer nio将两者统一为postion,然后弄出了读写模式切换的概念。

当从buffer里取出数据,即buffer.getXXX或者channel.write(buffer),

当往buffer里放入数据,即buffer.putXX或者channel.read(buffer),

的前后,经常要考虑模式的切换,比如调用flip,这样的设计增加了复杂性,对库的使用者带来困难(笔者才疏学浅,一直疑惑他们为什么这么设计,求高人指教),这本质上是因为position属性既要当作readindex来使用,又要当作writeindex来使用。

另外一点就是由于postion的大小不能超过limit和capacity, 导致使用的过程中经常需要compact, 每次compact会导致额外的内存拷贝;传统的ringbuffer会在writeindex < readindex在的时候才可能涉及到额外内存的拷贝。

也难怪,netty里抛弃了这种设计。

最近用libcurl向某商web服务器作登录校验踩了一坑。

事情的表象是这样的,在windows上没有问题,linux上投递过去的数据乱码。但是如果将curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data)中的data写死,即写成字符串常量,也是没有问题的。

开始以为一些参数和环境的问题,查了半天问题依旧,才怀疑到变量生存周期的问题,将data生命期拉长,就好了。

关于shadowsocks

平时其实很少使用VPN,多是Mac上SSH+Socks代理,Windows上就myentunnel+Socks代理。近来工作原因,手机上需要VPN才用的较为频繁,然而最近经常不好使了,  换了几个,一直都不太稳定,原因嘛你懂的。

于是在自己国外的VPS上搭建了一个VPN,用的是shadowsocks搭建的服务器.

客户端的话Mac,  Android , Windows应该都有免费的,iPhone上现在要花16元。

搭建好,用的是443端口。一天之后,发现不行了,然后换了个端口,现在已经流畅运行好几天了,很开心:)

一般的翻墙,通过设置浏览器http代理或者socks (5)代理就可以了。shadowsocks显然做的更多。

出于习惯,想了想这个自己弄应该怎么实现。去看了下代码,服务端用的python,几千行代码挺简洁的; 客户端需要解决的问题复杂些, 涉及到TCP/IP协议栈。