# Go网络与协议
![](https://img.kancloud.cn/a1/34/a13423b8125805ebfcf1e6f496cbaa2b_340x286.png)
**TCP/IP 协议族:**
* ARP: Address Resolution Protocol, 正向地址解析协议。通过已知的IP,寻找对应的主机MAC地址。
* RARP:是反响的地址转换协议,通过MAC地址确定IP地址。
* IP:Internet Protocol,是因特网互联协议
* ICMP:Internet Control Message Protocol,是Internet控制报文协议,它是TCP/IP协议的一个子协议,用于在IP主机、路由器之间传递控制消息。
eg: ping 127.0.0.1 就是用到了ICMP协议
* IGMP:Internet Group Management Protocol,是Internet组管理协议,它是因特网协议家族中的一个`组播`协议,该协议运行在主机和组播路由器之间。
* TCP:Transmission Control Protocol,传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。主要用于 文件传输
* UDP:User Datagram Protocol,是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。主要用于 聊天
* FTP
* Telnet
* TFTP
* NFS
![](https://img.kancloud.cn/b6/34/b634e73d270b8e8b653b4485fe89e0b4_362x219.png)
**通信的拆包与组包:**
![](https://img.kancloud.cn/23/2b/232b5055d020de81ce9949c1ffd32315_1044x398.png)
# Socket编程
TCP的 C/S架构:
**cs模型:客户端和服务器**
客户端 ===》 客户
1)主动请求服务
服务器 ===》 客服
1)被动提供服务
![](https://img.kancloud.cn/35/54/3554633dd947b94ef5f868d741ca36e6_438x477.png)
# Go网络通信编程
## 服务器端
![](https://img.kancloud.cn/5b/cd/5bcd8b5ebeaa6ebf7f97919468a1988c_1570x1019.png)
在区块链中,每一个节点既是服务器,也是客户端。
首先服务器在当前节点开启监听,protocol为tcp。在函数startserver退出后,关闭l服务器监听器ln句柄。
同时作为客户端,给中心节点发送version命令,请求区块版本(高度)检查和同步。
接下来进入无限循环,服务器监听器阻塞,等待客户端连接,并通过并发模式,接收来自客户端的连接请求,该并发任务协程会被放到服务器堆栈。该协程的名称是handleConnection。
## 客户端
![](https://img.kancloud.cn/e5/9e/e59eb764d4c5594093f48801b3fceea1_1369x874.png)
客户端通过方法net.Dial连接到服务器。在本函数执行完毕,将关闭与服务器的连接。
接下来将消息写入到conn通道。
## 服务器端
![](https://img.kancloud.cn/5b/86/5b86055a902112974a2f0621d9a17d95_850x1089.png)
服务器端接收到客户端的连接,阻塞解除,协程handleConnection被调用执行。
在handleConnection中,首先通过ioutil读取conn上的所有数据,然后解析命令。注意命令为12个字节(commandLength),request则是command+payload构成,payload在各个具体命令的handle中进行解析。
接下来,根据command,转到相应的处理函数中进行处理。
![](https://img.kancloud.cn/05/bf/05bfbe6cb721a1bae9d147a82b8ea649_1180x588.png)
最后关闭通信连接。
# 区块链的服务器和客户端
1、区块链是P2P网络,因此加入区块链的每一个节点,既是服务器,也是客户端。
所以,一般在sendData时候,都会将发送者的addr作为payload的一部分,发送给对方。
2、P2P通信,是点对点的强通信方式,多次请求-回答完成交互,从发送“麻烦告诉我你版本是什么”开始,发现本地版本比对方低,于是接着发送“麻烦告诉我你有什么”,对方将回复区块或交易的概要(哈希列表),再紧接着向对方要具体的数据(如某个区块或者某个交易)。
3、由于是P2P通信,所以每次请求-回答的数据都很小:在区块链中,每次请求只会请求一个区块的数据或者一个交易的数据,这将最大限度保证通信的可靠性。
# Multiaddress
多地址(通常缩写为multiaddr)是一种约定,用于将多层寻址信息编码为单个“面向未来”的路径结构。
例如:/ip4/127.0.0.1/udp/1234对两个协议及其基本寻址信息进行编码。 /ip4/127.0.0.1通知我们,我们需要IPv4协议的127.0.0.1回送地址,而/ udp / 1234告诉我们,我们希望将UDP数据包发送到端口1234。
可以组成多地址来描述地址的多个“层”。
例如,multiaddr`/p2p/QmYyQSo1c1Ym7orWxLYvCrM2EmxFTANf8wXmmE7DWjhx5N`唯一标识我的本地 IPFS 节点, 使用 libp2p的[注册的协议ID](https://github.com/multiformats/multiaddr/blob/master/protocols.csv)`/p2p/`和我的IPFS节点公钥的[multihash](https://docs.libp2p.io/reference/glossary/#multihash)。
## Multiaddr简介:
Multiaddr aims to make network addresses future-proof, composable, and efficient.
Current addressing schemes have a number of problems.
1. They hinder protocol migrations and interoperability between protocols.
2. They don't compose well. There are plenty of X-over-Y constructions, but only few of them can be addressed in a classic URI/URL or host:port scheme.
3. They don't multiplex: they address ports, not processes.
4. They're implicit, in that they presume out-of-band values and context.
5. They don't have efficient machine-readable representations.
Multiaddr solves these problems by modelling network addresses as arbitrary encapsulations of protocols.
* Multiaddrs support addresses for any network protocol.
* Multiaddrs are self-describing.
* Multiaddrs conform to a simple syntax, making them trivial to parse and construct.
* Multiaddrs have human-readable and efficient machine-readable representations.
* Multiaddrs encapsulate well, allowing trivial wrapping and unwrapping of encapsulation layers.
Multiaddr was originally[thought up by @jbenet](https://github.com/jbenet/random-ideas/issues/11).
翻译如下:
Multiaddr的目标是使网络地址可适应未来需求,可组合且高效。
当前的寻址方案具有许多问题。
1. 它们阻碍协议迁移和协议之间的互操作性。
2. 他们表现不佳。有很多X-over-Y构造,但是只有少数可以用经典的URI / URL或host:port方案进行寻址。
3. 它们不复用:它们寻址端口,而不是进程。
4. 它们是隐式的,因为它们假定带外值和上下文。
5. 它们没有有效的机器可读表示。
Multiaddr通过将网络地址建模为协议的任意封装来解决这些问题。
1. Multiaddr支持任何网络协议的地址。
2. Multiaddr是自我描述的。
3. Multiaddr遵循简单的语法,使其易于解析和构造。
4. Multiaddr具有人类可读和有效的机器可读表示形式。
5. Multiaddr可以很好地封装,从而可以轻松封装和解开封装层。
Multiaddr最初是由[@jbenet](https://github.com/jbenet/random-ideas/issues/11)想到的。
# 以太坊的KAD协议
以太坊Kad网络中节点间通信基于UDP,主要由以下几个命令构成,若两个节点间PING-PONG握手通过,则认为相应节点在线。
![](https://img.kancloud.cn/13/56/135653d8a2b611e50ccb5db93f3a76df_1374x1373.png)
# 以太坊的邻居节点
C++版本以太坊源码中,NodeTable是以太坊 P2P网络的关键类,所有与邻居节点相关的数据和方法均由NodeTable类实现。
![](https://img.kancloud.cn/97/e9/97e96fe3009635ceeab7a7ab1221e6d3_877x492.png)
![](https://img.kancloud.cn/58/81/5881c8451fd0846d3df795f7a488f93b_846x1295.png)
![](https://img.kancloud.cn/e4/25/e4252f9adeffcd2307d55afbf32b7e62_851x759.png)
## 邻居节点发现方法
邻居节点是指加入到K桶,并通过PING-PONG握手的节点。
![](https://img.kancloud.cn/b8/8b/b88bcdcfbafec5c738f968c411d9c4ec_629x651.png)
邻居节点发现流程说明:
1. 系统第一次启动随机生成本机节点NodeId,记为LocalId,生成后将固定不变,本地节点记为local-eth。
2. 系统读取公共节点信息,ping-pong握手完成后,将其写入K桶。
3. 系统每隔7200ms刷新一次K桶。
4. 刷新K桶流程如下:
a. 随机生成目标节点Id,记为TargetId,从1开始记录发现次数和刷新时间
b. 计算TargetId与LocalId的距离,记为Dlt
c. K桶中节点的NodeId记为KadId,计算KadId与TargetId的距离,记为Dkt
d. 找出K桶中Dlt大于Dkt的节点,记为k桶节点,向k桶节点发送FindNODE命令,FindNODE命令包含TargetId
e. K桶节点收到FindNODE命令后,同样执行b-d的过程,将从K桶中找到的节点使用Neighbours命令发回给本机节点。
f. 本机节点收到Neighbours后,将收到的节点写入到K桶中。
g. 若搜索次数不超过8次,刷新时间不超过600ms,则返回到b步骤循环执行。
## 邻居节点网络拓扑及刷新机制
![](https://img.kancloud.cn/0c/ba/0cbaaee11b8bc1264b6c62f1309627ef_640x735.png)
1 TargetId为随机生成的虚拟节点ID。
2 以太坊Kad网络与传统Kad网络的区别:
1. 以太坊节点在发现邻居节点的8次循环中,所查找的节点均在距离上向随机生成的TargetId收敛。
2. 传统Kad网络发现节点时,在距离上向节点本身收敛。
- 重要更新说明
- linechain发布
- linechain新版设计
- 引言一
- 引言二
- 引言三
- vs-code设置及开发环境设置
- BoltDB数据库应用
- 关于Go语言、VS-code的一些Tips
- 区块链的架构
- 网络通信与区块链
- 单元测试
- 比特币脚本语言
- 关于区块链的一些概念
- 区块链组件
- 区块链第一版:基本原型
- 区块链第二版:增加工作量证明
- 区块链第三版:持久化
- 区块链第四版:交易
- 区块链第五版:实现钱包
- 区块链第六版:实现UTXO集
- 区块链第七版:网络
- 阶段小结
- 区块链第八版:P2P
- P2P网络架构
- 区块链网络层
- P2P区块链最简体验
- libp2p建立P2P网络的关键概念
- 区块链结构层设计与实现
- 用户交互层设计与实现
- 网络层设计与实现
- 建立节点发现机制
- 向区块链网络请求区块信息
- 向区块链网络发布消息
- 运行区块链
- LineChain
- 系统运行流程
- Multihash
- 区块链网络的节点发现机制深入探讨
- DHT
- Bootstrap
- 连接到所有引导节点
- Advertise
- 搜索其它peers
- 连接到搜到的其它peers
- 区块链网络的消息订发布-订阅机制深入探讨
- LineChain:适用于智能合约编程的脚本语言支持
- LineChain:解决分叉问题
- LineChain:多重签名
- libp2p升级到v0.22版本
- 以太坊基础
- 重温以太坊的树结构
- 世界状态树
- (智能合约)账户存储树
- 交易树
- 交易收据树
- 小结
- 以太坊的存储结构
- 以太坊状态数据库
- MPT
- 以太坊POW共识算法
- 智能合约存储
- Polygon Edge
- block结构
- transaction数据结构
- 数据结构小结
- 关于本区块链的一些说明
- UML工具-PlantUML
- libp2p介绍
- JSON-RPC
- docker制作:启动多个应用系统
- Dockerfile
- docker-entrypoint.sh
- supervisord.conf
- docker run
- nginx.conf
- docker基础操作整理
- jupyter计算交互环境
- git技巧一
- git技巧二
- 使用github项目的最佳实践
- windows下package管理工具