如果我想在代码中的某处发送消息并处理响应,那么 API 是什么?我需要什么组件?我如何构造它们或获取它们的句柄?我调用什么方法?如何添加新的消息类型?
1 回答
这是我为作为下载提案引用的候选交易集的一部分而交换的消息制作的序列图:
要发送消息,组件需要一个PeerImp
对象(通常通过 保存shared_ptr<Peer>
),在该对象上调用send(shared_ptr<Message>)
方法。只有一个通用实现send
,它处理每个协议缓冲区消息类型。该调用返回void
(即没有请求对象)。
当从对等方接收到消息时,将onMessage(MessageType)
调用该消息类型的方法。每种消息类型都有不同的重载onMessage
。
考虑为 HTTP 编写代码时。JavaScript 中一个流行的习惯用法如下所示:
const response = await http.get(url, params)
这种模式与 RTXP(我们的消息协议的正式名称)的模式之间有一些重要的区别:
HTTP 在请求和响应之间有关联。RTXP 通常没有这种关联,但在一个值得注意的例子中它确实存在。
TMGetLedger
是请求消息类型,TMLedgerData
是其响应消息类型。它们都有一个requestCookie
字段来将响应与其请求相关联。请求为其“请求 cookie”生成一个(随机?)标识符,响应复制该 cookie。使用 HTTP,发送请求的代码会传递一个期望响应的处理程序。通常,响应处理程序对于发送请求的代码中的每个位置都是不同的。RTXP 并非如此。相反,每个请求消息类型通常对应于一个响应消息类型,并且给定类型的每个消息具有相同的确切处理程序。这意味着代码中发送相同消息类型的请求的每个地方都使用相同的响应处理程序。我怀疑:
大多数消息类型都是从代码中的一个地方发送的
当一种消息类型从多个地方发送时,该消息有一个枚举字段来区分它们(名称中带有“type”)
每种消息类型都是针对代码中需要发送它的位置而设计的,这使得它们难以重用
大多数请求消息类型与其响应消息类型不同。一个值得注意的例外是
TMGetObjectByHash
它有一个布尔query
字段,用于区分请求 (true
) 和响应 (false
)。
每种消息类型都有统一处理的空间:
通常期望消息是可独立验证的。如果响应说它有 ledger 的标头
ABCD
,则处理程序期望它可以散列标头以获取摘要ABCD
。通常期望响应对应于请求。
如果违反了这些期望,则发送消息的对等方将受到惩罚。我们的服务器会跟踪衡量其可靠性的每个对等方的“费用”。不良消息会根据违规类型“收取”各种费用。这些费用只存在于服务器上。它们与分类帐无关。
PeerImp
对象是从对象中获得的Overlay
。Overlay
per恰好有一个Application
,通过调用其overlay()
方法获得。