兄弟连区块链技术培训以太坊源码分析51rpc源码分析文档格式.docx
- 文档编号:17203433
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:41
- 大小:35.52KB
兄弟连区块链技术培训以太坊源码分析51rpc源码分析文档格式.docx
《兄弟连区块链技术培训以太坊源码分析51rpc源码分析文档格式.docx》由会员分享,可在线阅读,更多相关《兄弟连区块链技术培训以太坊源码分析51rpc源码分析文档格式.docx(41页珍藏版)》请在冰豆网上搜索。
Anexamplemethod:
func(s*CalcService)Add(a,bint)(int,error)
Whenthereturnederrorisn'
tnilthereturnedintegerisignoredandtheerroris
sendbacktotheclient.Otherwisethereturnedintegerissendbacktotheclient.
当返回的error不等于nil的时候,返回的整形值被忽略,error被发送回客户端。
否则整形的会返回被发送回客户端。
Optionalargumentsaresupportedbyacceptingpointervaluesasarguments.E.g.
ifwewanttodotheadditioninanoptionalfinitefieldwecanacceptamod
argumentaspointervalue.
通过提供指针类型的参数可以使得方法支持可选参数。
后面有点看不懂了。
func(s*CalService)Add(a,bint,mod*int)(int,error)
ThisRPCmethodcanbecalledwith2integersandanullvalueasthirdargument.
Inthatcasethemodargumentwillbenil.Oritcanbecalledwith3integers,
inthatcasemodwillbepointingtothegiventhirdargument.Sincetheoptional
argumentisthelastargumenttheRPCpackagewillalsoaccept2integersas
arguments.ItwillpassthemodargumentasniltotheRPCmethod.
RPC方法可以通过传两个integer和一个null值作为第三个参数来调用。
在这种情况下mod参数会被设置为nil。
或者可以传递三个integer,这样mod会被设置为指向第三个参数。
尽管可选的参数是最后的参数,RPC包任然接收传递两个integer,这样mod参数会被设置为nil。
TheserverofferstheServeCodecmethodwhichacceptsaServerCodecinstance.Itwill
readrequestsfromthecodec,processtherequestandsendstheresponsebacktothe
clientusingthecodec.Theservercanexecuterequestsconcurrently.Responses
canbesentbacktotheclientoutoforder.
server提供了ServerCodec方法,这个方法接收ServerCodec实例作为参数。
服务器会使用codec读取请求,处理请求,然后通过codec发送回应给客户端。
server可以并发的执行请求。
response的顺序可能和request的顺序不一致。
//AnexampleserverwhichusestheJSONcodec:
typeCalculatorServicestruct{}
func(s*CalculatorService)Add(a,bint)int{
returna+b
}
func(s*CalculatorServiceDiv(a,bint)(int,error){
ifb==0{
return0,errors.New("
dividebyzero"
)
}
returna/b,nil
calculator:
=new(CalculatorService)
server:
=NewServer()
server.RegisterName("
calculator"
calculator"
l,_:
=net.ListenUnix("
unix"
&
net.UnixAddr{Net:
"
Name:
/tmp/calculator.sock"
})
for{
c,_:
=l.AcceptUnix()
codec:
=v2.NewJSONCodec(c)
goserver.ServeCodec(codec)
Thepackagealsosupportsthepublishsubscribepatternthroughtheuseofsubscriptions.
Amethodthatisconsideredeligiblefornotificationsmustsatisfythefollowingcriteria:
firstmethodargumenttypemustbecontext.Context
methodmustreturnthetupleSubscription,error
该软件包还通过使用订阅来支持发布订阅模式。
被认为符合通知条件的方法必须满足以下条件:
第一个方法参数类型必须是context.Context
方法参数必须导出或内置类型
方法必须返回元组订阅,错误
func(s*BlockChainService)NewBlocks(ctxcontext.Context)(Subscription,error){
...
Subscriptionsaredeletedwhen:
theusersendsanunsubscriberequest
theconnectionwhichwasusedtocreatethesubscriptionisclosed.Thiscanbeinitiated
bytheclientandserver.Theserverwillclosetheconnectiononanwriteerrororwhen
thequeueofbufferednotificationsgetstoobig.
订阅在下面几种情况下会被删除
用户发送了一个取消订阅的请求
创建订阅的连接被关闭。
这种情况可能由客户端或者服务器触发。
服务器在写入出错或者是通知队列长度太大的时候会选择关闭连接。
##RPC包的大致结构
网络协议channels和Json格式的请求和回应的编码和解码都是同时与服务端和客户端打交道的类。
网络协议channels主要提供连接和数据传输的功能。
json格式的编码和解码主要提供请求和回应的序列化和反序列化功能(Json->
Go的对象)。
!
[image](picture/rpc_1.png)
##源码解析
###server.go
server.go主要实现了RPC服务端的核心逻辑。
包括RPC方法的注册,读取请求,处理请求,发送回应等逻辑。
server的核心数据结构是Server结构体。
services字段是一个map,记录了所有注册的方法和类。
run参数是用来控制Server的运行和停止的。
codecs是一个set。
用来存储所有的编码解码器,其实就是所有的连接。
codecsMu是用来保护多线程访问codecs的锁。
services字段的value类型是service类型。
service代表了一个注册到Server的实例,是一个对象和方法的组合。
service字段的name代表了service的namespace,typ实例的类型,callbacks是实例的回调方法,subscriptions是实例的订阅方法。
typeserviceRegistrymap[string]*service//collectionofservices
typecallbacksmap[string]*callback//collectionofRPCcallbacks
typesubscriptionsmap[string]*callback
typeServerstruct{
servicesserviceRegistry
runint32
codecsMusync.Mutex
codecs*set.Set
//callbackisamethodcallbackwhichwasregisteredintheserver
typecallbackstruct{
rcvrreflect.Value//receiverofmethod
methodreflect.Method//callback
argTypes[]reflect.Type//inputargumenttypes
hasCtxbool//method'
sfirstargumentisacontext(notincludedinargTypes)
errPosint//errreturnidx,of-1whenmethodcannotreturnerror
isSubscribebool//indicationifthecallbackisasubscription
//servicerepresentsaregisteredobject
typeservicestruct{
namestring//nameforservice
typreflect.Type//receivertype
callbackscallbacks//registeredhandlers
subscriptionssubscriptions//availablesubscriptions/notifications
Server的创建,Server创建的时候通过调用server.RegisterName把自己的实例注册上来,提供一些RPC服务的元信息。
constMetadataApi="
rpc"
//NewServerwillcreateanewserverinstancewithnoregisteredhandlers.
funcNewServer()*Server{
server:
=&
Server{
services:
make(serviceRegistry),
codecs:
set.New(),
run:
1,
//registeradefaultservicewhichwillprovidemetainformationabouttheRPCservicesuchastheservicesand
//methodsitoffers.
rpcService:
RPCService{server}
server.RegisterName(MetadataApi,rpcService)
returnserver
服务注册server.RegisterName,RegisterName方法会通过传入的参数来创建一个service对象,如过传入的rcvr实例没有找到任何合适的方法,那么会返回错误。
如果没有错误,就把创建的service实例加入serviceRegistry。
//RegisterNamewillcreateaserviceforthegivenrcvrtypeunderthegivenname.Whennomethodsonthegivenrcvr
//matchthecriteriatobeeitheraRPCmethodorasubscriptionanerrorisreturned.Otherwiseanewserviceis
//createdandaddedtotheservicecollectionthisserverinstanceserves.
func(s*Server)RegisterName(namestring,rcvrinterface{})error{
ifs.services==nil{
s.services=make(serviceRegistry)
svc:
=new(service)
svc.typ=reflect.TypeOf(rcvr)
rcvrVal:
=reflect.ValueOf(rcvr)
ifname=="
"
{
returnfmt.Errorf("
noservicenamefortype%s"
svc.typ.String())
//如果实例的类名不是导出的(类名的首字母大写),就返回错误。
if!
isExported(reflect.Indirect(rcvrVal).Type().Name()){
%sisnotexported"
reflect.Indirect(rcvrVal).Type().Name())
//通过反射信息找到合适的callbacks和subscriptions方法
methods,subscriptions:
=suitableCallbacks(rcvrVal,svc.typ)
//如果这个名字当前已经被注册过了,那么如果有同名的方法就用新的替代,否者直接插入。
//alreadyapreviousserviceregisterundergivensname,mergemethods/subscriptions
ifregsvc,present:
=s.services[name];
present{
iflen(methods)==0&
&
len(subscriptions)==0{
Service%Tdoesn'
thaveanysuitablemethods/subscriptionstoexpose"
rcvr)
for_,m:
=rangemethods{
regsvc.callbacks[formatName(m.method.Name)]=m
for_,s:
=rangesubscriptions{
regsvc.subscriptions[formatName(s.method.Name)]=s
returnnil
svc.name=name
svc.callbacks,svc.subscriptions=methods,subscriptions
iflen(svc.callbacks)==0&
len(svc.subscriptions)==0{
s.services[svc.name]=svc
通过反射信息找出合适的方法,suitableCallbacks,这个方法在utils.go里面。
这个方法会遍历这个类型的所有方法,找到适配RPCcallback或者subscriptioncallback类型标准的方法并返回。
关于RPC的标准,请参考文档开头的RPC标准。
//suitableCallbacksiteratesoverthemethodsofthegiventype.Itwilldetermineifamethodsatisfiesthecriteria
//foraRPCcallbackorasubscriptioncallbackandaddsittothecollectionofcallbacksorsubscriptions.Seeserver
//documentationforasummaryofthesecriteria.
funcsuitableCallbacks(rcvrreflect.Value,typreflect.Type)(callbacks,subscriptions){
callbacks:
=make(callbacks)
subscriptions:
=make(subscriptions)
METHODS:
form:
=0;
m<
typ.NumMethod();
m++{
method:
=typ.Method(m)
mtype:
=method.Type
mname:
=formatName(method.Name)
ifmethod.PkgPath!
="
{//methodmustbeexported
continue
varhcallback
h.isSubscribe=isPubSub(mtype)
h.rcvr=rcvr
h.method=method
h.errPos=-1
fir
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 兄弟连 区块 技术培训 以太 源码 分析 51 rpc