绑定表
1. 绑定表存放的位置是内存中预先定义的RAM块,如果编译选项NV_RESTORE被激活,也能保存在Flash里。
2. 绑定表放置在源节点(需要激活编译选项REFLECTOR)。
3. 绑定表的条目把需要发送的消息映射到它们的目标地址上。
4. 绑定表中每个条目(entry)包括以下内容:
绑定表条目结构体的定义
typedef struct
{
uint16 srcIdx; //源地址索引
uint8 srcEP; //源端点
uint8 dstGroupMode; //指定寻址模式
uint16 dstIdx; //目标地址索引或者分组号
uint8 dstEP; //目标端点
uint8 numClusterIds; //在簇标识符表中簇标识符的个数
uint16 clusterIdList[MAX_BINDING_CLUSTER_IDS]; //簇标识符表
}BindingEntry_t;
有两种机制可供选择。
1、如果目标设备的扩展地址(64位地址)已知,可通过调用zb_BindDeviceRequest()建立绑定条目。
2、如果目标设备的扩展地址未知,可实施一个“按键”策略实现绑定。这时,目标设备将首先进入一个允许绑定的状态,并通过zb_AllowBindResponse()对配对请求作出响应。然后,在源节点中执行zb_BindDeviceRequest()(目标地址设为无效)可实现绑定。
下面引用《zigbee2006无线网络与无线定位实战》对未知扩展地址的绑定流程的描述(以simpApp灯开关实验为例),根据协议版本不同作了相应修改:
(1)首先调用zb_AllowBind(myAllowBindTimeout)函数,使管理设备(灯)处于允许绑定(匹配)响应模式
(2)在myAllowBindTimeout规定的时间内,终端设备(开关)需要调用zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID, NULL)函数发送绑定(描述符匹配ZDP_MatchDescReq)请求.
(3)当管理器接收到匹配请求后,对该匹配作出响应,发送一个匹配响应(P:在ZDO_ProcessMatchDescReq()函 数 中),之后可以看到发送匹配响应后的确认事件(P:在ZDO_ProcessMatchDescReq()函数中): pRspSent->hdr.event = ZDO_MATCH_DESC_RSP_SENT
(4)当终端接收到匹配响应后,产生该事件: case Match_Desc_rsp:详细处理过程看SAPI_ProcessZDOMsgs,这里 面调用了APSME_BindRequest()建立绑定,而且调用 了ZDP_IEEEAddrReq()得到被绑定的IEEE地址.
(5)最后完成绑定,在终端设备建立绑定表格.
时序图:
管理器(灯) 终端(开关)
1、-------------允许绑定模式 ----------------------- ----------
2、------------- --<----<---<--------广播发送描述符匹配请求(绑定请求)
3、-----接收后发送描述符匹配响应-->--->--->-- -----------
4、------------- ---------------------接收后获得管理器地址,建立终端与管理器间的绑定---
补充:
第二步:
终端调用zb_BindDevice()发送描述符匹配请求(即绑定请求)给管理器.其中调用ZDP_MatchDescReq()函数建立和发送一个匹配描述请求.
//使用这个函数查询与应用程序输入或输出簇列表相匹配的应用程序或设备. //即发现服务,或者叫自动寻求匹配设备
第三步:管理器接收到终端发送的描述符匹配请求(也即绑定请求). 那管理器是如何作出处理的?
绑定是基于设备应用层端点的绑定,绑定是在协议栈的APS层实现的。 APS提供了接口:在NWK层和APL层之间,从ZDO到供应商的应用对象的通用服务集。这服务由两个实体实现:APS数据实体(APSDE)和APS管理实体(APSME)。 (1)APSDE提供在同一个网络中的两个或者更多的应用实体之间的数据通信。通过APSDE服务接入点(APSDE-SAP); (2)APSME提供多种服务给应用对象,这些服务包含安全服务和绑定设备,并维护管理对象的数据库,也就是我们常说的AIB。通过APSME服务接入点(APSME-SAP)。 ZDO有以下功能: (1)初始化应用支持子层(APS),网络层(NWK),安全服务提供(SSP)和任何其他ZigBee设备层 (2)从终端应用中集合配置信息来确定和执行下节描述的功能。
因为这里是接收到描述符匹配请求,SAPI_Init中没有注册过这个ZDO信息,因此不会通过ZDO_SendMsgCBs()发送到sapi应用.然后查询ZDO信息处理表,当x=6时发现命令相符,调用ZDO_ProcessMatchDescReq()对描述符匹配请求进行处理 其中调用ZDP_MatchDescRsp()发送匹配响应给终端.而ZDP_MatchDescRsp()宏定义为ZDP_EPRsp(),ZDP_EPRsp()设置clusterID为Match_Desc_rsp并调用 FillAndSendTxOptions(),FillAndSendTxOptions()中调用fillAndSend(),fillAndSend()中最终调用AF_DataRequest()来发送匹配响应给终端(灯).发送完匹配响应后管理器触发一个确认事件ZDO_MATCH_DESC_RSP_SENT,来指示有个设备试图与自己绑定.管理器是如何对这个确认事件进行处理的?如下:
SAPI_ProcessEvent()中对ZDO_MATCH_DESC_RSP_SENT的处理case ZDO_MATCH_DESC_RSP_SENT:
/*发送匹配响应*/
SAPI_AllowBindConfirm( ((ZDO_MatchDescRspSent_t *)pMsg)->nwkAddr );
第四步:终端接收到管理器发送的描述符匹配响应.
同样,这个响应信息也是发往ZDO层的,因此首先要来看ZDP_IncomingData()这个函数,具体见第三步.因为接收到的响应信息clusterID为Match_Desc_rsp,SAPI_Init注册过,因此会通过
ZDO_SendMsgCBs()把这个描述符匹配响应信息发送到sapi应用层,而在ZDO信息处理表中查询不到相符合的clusterID,因此不会调用任何处理函数.这里刚好与第二步中对描述符匹配请求的处理相反.下面来看下ZDO_SendMsgCBs()把这个描述符匹配响应信息发送到sapi应用层后的处理,
ZDO_SendMsgCBs()发送的流程参见第三步,其最终触发任务sapi的ZDO_CB_MSG事件,而sapi任务事件处理函数SAPI_ProcessEvent()通过调用SAPI_ProcessZDOMsgs()对其进行处理:
一、 “终端设备绑定请求”这一命名有误导的嫌疑。这一请求不仅仅适用于终端设备,而且适用于对希望在协调器上绑定的两个设备中匹配的簇实施绑定。一旦这个函数被调用,将假设REFLECTOR这一编译选项在所有希望使用这一服务的节点中都已经打开。具体操作如下:
(1) (Bind Req) Device 1 --> Coordinator <--- Device 2 (Bind Req)
协调器首先找出包含在绑定请求中的簇,然后对比每一设备的IEEE地址,如果簇可以匹配,而且这几个设备没有已经存在的绑定表,那他将发送一个绑定应答给每一个设备。
(2) Device 1 <--- NWK Addr Req ------ Coordinator ------- NWK addr Req ----> Device 2 (3) Device 1 ----> NWK Addr Rsp ---> Coordinator <---- NWK addr Rsp <--- Device 2 (4) Device 1 <----- Bind Rsp <----- Coordinator -----> Bind Rsp ----> Device 2
二、 “描述符匹配”为源设备的服务发现提供了一种灵巧的方法。下面是具体的操作,这一过程并没有通过协调器。
(1) Device 1 ----> Match Descriptor request (broadcast or unicast) Device 2
(2) Device 1 <---- Match Descriptor response (if clusters, application profile id match) that includes src endpoint, src address <---- Device 2 1号设备需要维护一个端点和地址的记录。 许多应用服务最终都会使用第二种方法。
以上两种绑定机制,最终都是用函数APSME_BindRequest()创建绑定。不同的是,前者采用的目的地址是64位扩展地址,而后者采用的目的地址是16位网络地址。前者已知扩展地址,调用了ZDP_NwkAddrReq()函数获得目的设备短地址;后者利用描述匹配得到了短地址,然后调用了ZDP_IEEEAddrReq()函数,获取目的设备的扩展地址.
1.自动绑定-- 这种方法有时也称“服务发现”,“自动找寻”或者“自动匹配”
一、 负责发送消息的设备在网络上广播带有如下参数的“个人公告”(Personal Advertisement):
(1) 地址(Address),配置文件标识符(Profile ID),簇集合列表(Cluster Lists);
(2) 描述符匹配请求- ZDP_MatchDescReq()。
二、 匹配的设备会作出响应。
三、 由ZDO处理和验证响应。
四、 负责发送消息的设备建立绑定表并保存绑定记录。
。
2、ZigBee设备对象绑定请求---一种告诉目标设备建立绑定记录的委托工具,
任何一个设备或应用服务,都能通过无线信道向网络上的另一个设备发送一个ZDO消息,帮助其建立一个绑定记录。也称辅助绑定、援助绑定,在消息发向的设备上会建立一个绑定条目。
委托绑定的申请:
任一个应用服务,通过向ZDP_BindReq()[defined in ZDProfile.h]提供绑定记录所需要的应用服务入口参数(地址和端点)以及簇标识号(cluster ID),即可启动委托绑定的申请。第一个参数(消息发送目标地址)是绑定源节点的短地址(即保存绑定记录的节点地址,这是因为ZDP需委托应用框架AF辅助实现绑定,如果节点本身是REFLECTOR,并且希望保存绑定记录,则此消息发送的目标地址就是本地的AF,这与目标节点地址DestinationAddr of Receiving device不同)。
注意事项:
l 确保[ZDConfig.h]中ZDO_BIND_UNBIND_REQUEST特性已经打开!
l 你可以通过ZDP_UnbindReq()(使用相同参数)来移除绑定记录。
l 被请求辅助绑定的目标设备会返回的ZDO申请绑定或者解除绑定的应答消息。此ZDO消息会被解析并通过调用ZDApp_BindRsp()或ZDApp_UnbindRsp()告知ZDApp.c此次请求的结果。
l 对于申请绑定的应答消息,从协调器返回的状态可能有ZDP_SUCCESS,ZDP_TABLE_FULL or ZDP_NOT_SUPPORTED。
l 对于解除绑定的应答消息,从协调器返回的状态可能有ZDP_SUCCESS,ZDP_NO_ENTRY or ZDP_NOT_SUPPORTED。
l 绑定是由外部的设备发起(“外部”的意思是发起绑定的不是绑定的对象之一)。
l 外部设备应用程序以两个应用服务(地址和端点)和簇标识符作为参数调用ZDP_BindReq ()发起绑定。第一个参数就是绑定记录保存的设备地址。委托绑定。
l 确保编译选项REFLECTOR已经打开!
函数解析:
ZDP_BindReq()实际上是调用ZDP_BindUnbindReq()的一个宏。这一调用会产生并发送一个绑定的请求,使得ZigBee协调器根据簇标识号clusterID对相应的应用服务实施绑定。
函数原型:
afStatus_t ZDP_BindReq(zAddrType_t*dstAddr,byte*SourceAddr,
byte SrcEPIntf,byte ClusterID,byte*DestinationAddr,byte DstEPIntf,
byte SecuritySuite);
参数细节:
DstAddr-消息发送地址 (负责绑定的设备地址,本地的AF)-参见上面委托绑定
SourceAddr–源节点的64位IEEE地址
SrcEPIntf–源节点应用服务的端点
ClusterID–需要绑定的簇标识符
DestinationAddr–目标节点的64位IEEE地址
DstEPIntf–目标节点应用服务的端点
SecuritySuite-安全机制模式
返回值:
afStatus_t–此函数需要借助AF发送(AF_DataRequest())生成的消息,因此返回值是AF状态值。
3、ZigBee设备对象终端节点绑定请求---两个设备可向协调器告知他们想建立一个绑定表记录。协调器通过安排配对并分别在这两个设备上建立绑定表条目,也称集中式绑定。
这一机制规定在指定的时限内,通过按键或者其他类似动作对指定的设备实施绑定。在规定的时限内,协调器负责收集终端设备绑定请求消息,然后根据相同的配置文件标识号(profile id)和簇标识号(cluster id)建立相应的绑定表格条目。默认的终端节点绑定时限(APS_DEFAULT_MAXBINDING_TIME)是16秒(在nwk_globals.h中定义),若要修改可在f8wConfig.cfg中新增数值。
所有例子的应用服务中都有一个响应按键事件的函数(例如,TransmitApp.c中的TransmitApp_HandleKeys())。这一响应函数调用ZDApp_SendEndDeviceBindReq()[在 ZDApp.c中]收集该应用服务端点的所有信息,然后再调用ZDP_EndDeviceBindReq()[在ZDProfile.c中]把信息发送给协调器。或者,像SampleLight和SampleSwitch例程中,按键后直接调用ZDP_EndDeviceBindReq(),仅把与开关灯函数相关的簇标识号发送出去。
这一消息将会被协调器接收[ZDP_IncomingData()in ZDProfile.c]和解析[ZDO_ProcessEndDeviceBindReq()in ZDObject.c],然后让回调函数ZDApp_EndDeviceBindReqCB()[in ZDApp.c]调用ZDO_MatchEndDeviceBind()[ZDObject.c]处理这一请求。
当协调器接收到第一个绑定请求时,他会在一定的时限内保留这一请求并等待第二个请求的出现。(默认的最长时间间隔是16秒)。
一旦协调器接收到两个需要匹配的终端设备绑定请求时,它就会启动绑定过程,为发出请求的设备建立源绑定条目。假设在ZDO终端设备绑定请求中找到匹配,协调器将采取以下步骤:
1. 协调器发送一个ZDO解除绑定请求给第一个设备。终端设备绑定 是一个切换过程,所以解除绑定请求需要发送给第一个设备,以便移除一个已有的绑定条目。
2. 等待ZDO解除绑定的应答,如果返回的状态是ZDP_NO_ENTRY(没有已存在的绑定),协调器可以发送一个ZDO绑定请求,在源设备(ZDP_EndDeviceBindReq()第一个参数指定的地址)中建立绑定条目。假如此时返回的状态是ZDP_SUCCESS,可继续处理第一个设备的簇标识符(解除绑定指令已经移除了绑定条目,即已经切换完成)。
3. 等待ZDO绑定应答。收到以后,继续处理第一个设备的下一个簇标识符。
4. 等第一个设备完成了以后,在第二个设备上实行同样的过程。
5. 等第二个设备也完成了,协调器向两个设备发送ZDO终端设备绑定应答消息。
注意打开编译选项:REFLECTOR和ZDO_COORDINATOR
ZDApp_SendEndDeviceBindReq()
优点:
1. 绑定信息保存在网络反射设备(例如协调器、路由器)中,可以节省目标设备的内存空间。
2. 网络反射设备总是处于监听网络的状态。所以,如果其中一个被绑定的节点广播网络地址改变的消息,网络反射设备就可以马上更新相应的绑定表条目。这样,其他被绑定的节点即使处于休眠状态(没有收到该节点网络地址改变的消息),随后向该节点(网络地址已改变)发送的消息,(在)网络反射设备(协助下)仍能准确定位。
缺点:
1. 一个与多个设备绑定的节点不能只向一个或若干个配对的设备发送消息。网络反射设备会向全部已绑定的设备本别发送单播消息。
2. 发送消息的设备无法收到目标设备接收情况的通告。(没有像AF_ACK_REQUEST标志位那样返回接收情况的功能!)
3. 所有的消息必须经过网络反射设备传输,降低了网络的带宽。
进一步分析:
与六个设备绑定的某个设备,向网络反射器发送一个消息后,会导致反射器发送六个单播消息。假设一个网络被分成两个相等的地理区域A和B,网络反射器在两区之间的中央。如果发送消息的设备在A区的深处,接收消息的(六个)设备在B区的深处,那么每次通过绑定(向反射器)发送一个消息,A区的网络流量将会是对六个接收设备分别发送消息时的六分之一。(这是优点!)但如果发送和接收的设备都邻近在一个区的深处(假设离反射器很远),那么(其中一个设备通过反射器的绑定功能向其他设备发送一个消息)该区的网络流量将会是对六个接收设备分别发送单跳消息的许多倍。(这是缺点!)
4。设备的应用绑定管理----设备上的一个应用服务可以建立或者维护一个绑定表。进入设备上绑定条目的另一种方法是由应用服务本身去管理绑定表。
这意味着应用服务通过调用以下的绑定表管理函数,可以在本地进入或者移除绑定表的条目。
管理绑定表使用的API:
bindAddEntry()–绑定表中加条目
bindRemoveEntry()–绑定表中移除条目
bindRemoveClusterIdFromList()–从一个已有的绑定表条目中移除一个簇标识符
bindAddClusterIdToList()–在一个已有的绑定表条目中加入一个簇标识符
bindRemoveDev()–移除某目标地址的所有条目
bindRemoveSrcDev()–移除某源地址的所有条目
bindUpdateAddr()–更新条目到新的地址
bindFindExisting()–查找一个绑定条目
bindIsClusterIDinList()–在绑定条目中查找一个已有的簇标识符
bindNumBoundTo()–某一地址(源地址或目标地址)绑定条目的个数
bindNumOfEntries()–绑定表条目的个数
bindCapacity()–允许的最大绑定条目数
BindWriteNV()–在NV中保存新的绑定表
Which Binding Method To Use?
我们应该选择哪一种绑定方式?
Automatic
+no user interaction required
+no tool cost
-development time knowledge
-non-configurable
Assisted
+install-time decisions(site-specific knowledge)
+analysis,maintenance,modification,visualization
can be under installers control
-cost of tool
Centralized
+allows user to decide
+cost of tool minimal
-few,if any,configurable parameters
-requires a user interface on each device
Application
+maximum flexibility
-you must write all the code
来自TI E2E社区的进一步讨论:
一、“终端设备绑定请求”这一命名有误导的嫌疑。这一请求不仅仅适用于终端设备,而且适用于对希望在协调器上绑定的两个设备中匹配的簇实施绑定。一旦这个函数被调用,将假设REFLECTOR这一编译选项在所有希望使用这一服务的节点中都已经打开。具体操作如下:
(1) (Bind Req) Device 1 --> Coordinator <--- Device 2 (Bind Req)
协调器首先找出包含在绑定请求中的簇,然后对比每一设备的IEEE地址,如果簇可以匹配,而且这几个设备没有已经存在的绑定表,那他将发送一个绑定应答给每一个设备。
(2) Device 1 <--- NWK Addr Req ------ Coordinator ------- NWK addr Req ----> Device 2
(3) Device 1 ----> NWK Addr Rsp ---> Coordinator <---- NWK addr Rsp <--- Device 2
(4) Device 1 <----- Bind Rsp <----- Coordinator -----> Bind Rsp ----> Device 2
二、“描述符匹配”为源设备的服务发现提供了一种灵巧的方法。下面是具体的操作,这一过程并没有通过协调器。
(1) Device 1 ----> Match Descriptor request (broadcast or unicast) Device 2
(2) Device 1 <---- Match Descriptor response (if clusters, application profile id match) that includes src endpoint, src address <---- Device 2
1号设备需要维护一个端点和地址的记录。
许多应用服务最终都会使用第二种方法。
重谈Zigbee的绑定问题
一、绑定方式再解释
Zigbee绑定的四种方式:
1、 两个节点分别通过按键机制调用ZDP_EndDeviceBindReq函数
即:在一定时间内两个节点都通过按键(其他方式也可以)触发调用这个函数
特点:这个函数的调用将会向协调器发出绑定请求(具体如何调用及参数设置请看协议栈相关代码),如果在16S(协议栈默认)时间内两个节点都执行了这个函数,协调器就会帮忙实现绑定,这个过程的代码很复杂,我不想说。绑定表应该是存在OutCluster那边,即这两个节点应该是一个输出控制命令,一个接收控制命令,绑定表存在输出控制命令这边,至于如何实现,有兴趣同学可以继续研究代码。
注意:这种方式一定需要协调器,否则不行;但是一旦绑定成功,不再需要协调器,协调器只是帮忙绑定的一个第三方;虽然叫做EndDeviceBind,但是不局限于End Device,路由器也一样用;重复上述操作会解绑定,也就是说这是一个乒乓方式。 2、 Match方式
即:一个节点可以通过调用afSetMatch函数允许或禁止本节点被Match(协议栈默认允许,可以手工关闭),然后另外一个节点在一定的时间内发起ZDP_MatchDescReq请求,允许被Match的节点会响应这个Req,发起的节点在接收到RSP的时候就会自动处理绑定。
特点:不需要别人帮忙,只要在网络中的节点互相之间就可以实现,但是前提是他们一定要Match,即一方的outcluster至少有一个是另外一方的incluster,这种方式在很多时候用起来比较方便。
注意:如果同时有多个节点(一个节点上的多个端点也一样)处于允许Match状态,那么req的这个节点可能会收到一大票满足Match条件的rsp,那么你发起req的节点要在这个处理上多下功夫了。
3、 ZDP_BindReq和ZDP_UnbindReq方式
即:应用程序通过调用这两个函数实现绑定和解绑定,这种方式很有趣。具体说来是为了让A和B绑定到一起,还需要一个节点C。例如:你想A控制B,那么这种方式是由C发出bind或unbind命令给A(发给谁谁就处理绑定、并负责存储绑定表),A在接收到req的时候直接处理绑定,也就是添加绑定表项,并且这个过程B并不知道。但是A知道绑定表里面有了关于控制B的记录,并且这种方式可以实现一个节点绑定到一个Group上去。
注意:这种方式需要知道A和B的长地址,具体协议栈拿长地址做什么用,有兴趣的就去挖代码好了。 4、 手工管理绑定表
即:通过应用程序调用诸如bindAddEntry(函数在BindingTable.h文件中定义,具体实现被封包了)来实现手工绑定表管理,这种方式自由度很大,也不需要别的节点参与,但是应用程序要做的工作多一些,整个绑定表都是你说了算。
注意:这种方式你需要事先知道被绑定的节点信息,诸如短地址,端点号,incluster和outcluster这些信息,否则你没办法把那些函数的参数填进去。
二、应用场合举例
1、第一种方式(enddevicebind)
例:网络中有协调器存在,另外有两个节点A和B,这两个节点具有互补特性(即A节点的incluster是B节点的outcluster),A和B结点都有按钮可以通过程序来触发EndDeviceBind的调用。在这种情况下,你只要在规定的时间内分别按A和B上的某个按钮,绑定就会在协调器的帮助下自动完成。这适合于节点很方便操作,没有被装墙里或者无法接触的地方;绑定完成后,具有outcluster性质的B节点即可以通过绑定方式给具有incluster性质的A节点发消息,但是不能指望反过来由A发消息给B,因为A节点根本就没有关于B的信息,绑定表是存在B中的。
2、第二种方式(Match)
例:网络中不一定有协调器存在,但是有A、B、C、D等多个节点,A性质是Outcluster,B、C、D的性质是Incluster,你可以通过按键策略来在一定时间内允许B、C、D中的任何一个开启被Match的功能,同时A发起Match请求(广播的),那么被允许Match的节点就会在收到请求后将自己的信息返给A,A在得到rsp的时候来处理绑定,如果你还想让A绑到其它节点上,可以依次这么做。这种方式其实同第一种操作过程类似,只不过不需要协调器的参与。
3、第三种方式(Bindreq,Unbindreq)
例:假设你有一个主控(可能是ARM板子,可能是PC……),并且有一个Zigbee节点A通过串口或者U口等方式连在了主控上,主控可以给A发命令(什么命令你要自己定义、自己实现了);你还有一个B节点是开关,还有一个C节点是灯。你想让在B上建立绑定表,以用来控制C。那么你可以通过主机命令A向另外的节点B发起BindReq要求,主机发给A的命令中会带着C的一些信息(主机如何有C的信息?这种场合下,主机应该了解整个网络的细节,至于如何了解。。。。,以后再说)。这样,A就可以向B发起BindReq请求,这个请求的参数中包含了必要的C的信息,B在收到请求后就会建立起关于控制C的绑定表,以后B可以通过开关控制C了,也不再需要A的参与。这种方式适合那种集中管理的网络。 5、 第四种方式(手工)
例:你还是有一个主机,主机上有Zigbee节点A能够串口或者U口通信。你想由主机来深入地管理整个网络上的绑定情况,你就可以通过主机给A发命令,告诉A给某一个节点发命令,让它去建立、删除、追加。。。。绑定表。这种方式实际上最灵活,但是需要用左的工作最多,用户也需要很清晰的思路去管理绑定表,要是不小心管理错了,就杯具了。
还要补充说明的是:为什么要用绑定?尤其是3,4两种,都知道了被绑定节点的具体信息了?绑定有必要吗?实际上,在每一个节点入网的时候,都会向网络自动发出DeviceAnnce报告(这里面包含了节点的IEEE地址和新得到的短地址),告诉大家自己来了,在看到这个DeviceAnnce的时候,每个节点都会根据IEEE地址信息更新自己的绑定表的,这样你就不怕短地址变化啦。还有的时候你可能根本就不知道某些节点的具体信息,尤其是EP信息,在这种情况下,如果你没有主机来统一管理,再不用绑定,两个节点想通信是不可能的。