節(jié)點(diǎn)間通過XMLRPC建立連接
在一個節(jié)點(diǎn)剛啟動的時候,它并不知道其它節(jié)點(diǎn)的存在,更不知道它們在交談什么,當(dāng)然也就談不上通信。
所以,它要先與master對話查詢其它節(jié)點(diǎn)的狀態(tài),然后再與其它節(jié)點(diǎn)通信。
而節(jié)點(diǎn)與master對話使用的就是XMLRPC。
從這一點(diǎn)來看,master叫節(jié)點(diǎn)管理器確實(shí)名副其實(shí),它是一個大管家,給剛出生的節(jié)點(diǎn)提供服務(wù)。
下面我們以兩個節(jié)點(diǎn):talker和listener為例,介紹其通過XMLRPC建立通信連接的過程,如下圖所示。
- talker注冊
假設(shè)我們先啟動talker。啟動后,它通過1234端口使用XMLRPC向master注冊自己的信息,包含所發(fā)布消息的話題名。master會將talker的注冊信息加入注冊列表中;
2.listener注冊
listener啟動后,同樣通過XMLRPC向master注冊自己的信息,包含需要訂閱的話題名;
3.master進(jìn)行匹配
master根據(jù)listener的訂閱信息從注冊列表中查找,如果沒有找到匹配的發(fā)布者,則等待發(fā)布者的加入,如果找到匹配的發(fā)布者信息,則通過XMLRPC向listener發(fā)送talker的地址信息。
4.listener發(fā)送連接請求
listener接收到master發(fā)回的talker地址信息,嘗試通過XMLRPC向talker發(fā)送連接請求,傳輸訂閱的話題名、消息類型以及通信協(xié)議(TCP或者UDP);
5.talker確認(rèn)連接請求
talker接收到listener發(fā)送的連接請求后,繼續(xù)通過XMLRPC向listener確認(rèn)連接信息,其中包含自身的TCP地址信息;
6.listener嘗試與talker建立連接
listener接收到確認(rèn)信息后,使用TCP嘗試與talker建立網(wǎng)絡(luò)連接。
7.talker向listener發(fā)布消息
成功建立連接后,talker開始向listener發(fā)送話題消息數(shù)據(jù),master不再參與。
從上面的分析中可以發(fā)現(xiàn),前五個步驟使用的通信協(xié)議都是XMLRPC,最后發(fā)布數(shù)據(jù)的過程才使用到TCP。
master只在節(jié)點(diǎn)建立連接的過程中起作用,但是并不參與節(jié)點(diǎn)之間最終的數(shù)據(jù)傳輸。
節(jié)點(diǎn)在請求建立連接時會通過master.cpp文件中的execute()函數(shù)調(diào)用XMLRPC庫中的函數(shù)。
我們舉個例子,加入talker節(jié)點(diǎn)要發(fā)布消息,它會調(diào)用topic_manager.cpp中的TopicManager::advertise()函數(shù),在函數(shù)中會調(diào)用execute()函數(shù),該部分代碼如下。
XmlRpcValue args, result, payload;
args[0] = this_node::getName();
args[1] = ops.topic;
args[2] = ops.datatype;
args[3] = xmlrpc_manager_- >getServerURI();
master::execute("registerPublisher", args, result, payload, true);
其中,registerPublisher就是一個遠(yuǎn)程過程調(diào)用的方法(或者叫函數(shù))。節(jié)點(diǎn)通過這個遠(yuǎn)程過程調(diào)用向master注冊,表示自己要發(fā)布發(fā)消息了。
你可能會問,registerPublisher方法在哪里被執(zhí)行了呢?我們來到ros_comm-noetic-develtoolsrosmastersrcrosmaster路徑下,打開master_api.py文件,然后搜索registerPublisher這個方法,就會找到對應(yīng)的代碼,如下。
匆匆掃一眼就知道,它在通知所有訂閱這個消息的節(jié)點(diǎn),讓它們做好接收消息的準(zhǔn)備。
你可能注意到了,這個被調(diào)用的XMLRPC是用python語言實(shí)現(xiàn)的。
也就是說,XMLRPC通信時只要報(bào)文的格式是一致的,不管C++還是python語言,都可以實(shí)現(xiàn)遠(yuǎn)程調(diào)用的功能。
def registerPublisher(self, caller_id, topic, topic_type, caller_api):
try:
self.ps_lock.acquire()
self.reg_manager.register_publisher(topic, caller_id, caller_api)
# don't let '*' type squash valid typing
if topic_type != rosgraph.names.ANYTYPE or not topic in self.topics_types:
self.topics_types[topic] = topic_type
pub_uris = self.publishers.get_apis(topic)
sub_uris = self.subscribers.get_apis(topic)
self._notify_topic_subscribers(topic, pub_uris, sub_uris)
mloginfo("+PUB [%s] %s %s",topic, caller_id, caller_api)
sub_uris = self.subscribers.get_apis(topic)
finally:
self.ps_lock.release()
return 1, "Registered [%s] as publisher of [%s]"%(caller_id, topic), s
-
節(jié)點(diǎn)
+關(guān)注
關(guān)注
0文章
220瀏覽量
24527 -
管理器
+關(guān)注
關(guān)注
0文章
248瀏覽量
18616 -
MASTER
+關(guān)注
關(guān)注
0文章
104瀏覽量
11331 -
ROS
+關(guān)注
關(guān)注
1文章
280瀏覽量
17100
發(fā)布評論請先 登錄
相關(guān)推薦
評論