nanomsg 1.1.5 源代碼分析 (二)

這里分別分析server端和client端的過程。使用的協(xié)議為xpub/xsub,底層協(xié)議為IPC。

1. server端 (xpub)

1.1 nn_socket()

nn_socket()創(chuàng)建一個(gè)nn_sock表示nanomsg socket,domain和protocol指定了協(xié)議類型。

int nn_socket (int domain, int protocol);

nn_sock的成員sockbase指向協(xié)議對(duì)象,也就是nn_sockbase派生類的實(shí)例,這里是nn_xpub。nn_xpub用自身指定sockbase的值,還用自己的虛函數(shù)nn_xpub_sockbase_vfptr設(shè)置nn_sockbase的虛函數(shù)表vfptr。

nn_xpub與底層傳輸協(xié)議對(duì)象間需要一個(gè)數(shù)據(jù)通道,它的成員outpipes就是保存該通道的。當(dāng)連接準(zhǔn)備好時(shí),底層對(duì)象會(huì)調(diào)用nn_sockbase_vfptr->add()通知nn_xpub。(對(duì)nn_xpub來說,add()是nn_xpub_add())

nn_socket()首先在nn_global的nn_sock[]中找到空閑位置,然后調(diào)用nn_global_create_socket()創(chuàng)建nn_sock對(duì)象。

  • nn_sock_init()初始化nn_sock對(duì)象。因?yàn)閚n_sock是頂層對(duì)象,所以用nn_fsm_init_root()初始化。
  • nn_efd_init()初始化文件描述符sndefd和rcvfd分別用于發(fā)送和接收。
  • 在全局?jǐn)?shù)組nn_socktypes[]中保存了所有協(xié)議對(duì)象的創(chuàng)建信息nn_socktype。nn_sock_init()根據(jù)調(diào)用者指定的domain和protocol,在其中查找對(duì)應(yīng)的nn_socktype,然后調(diào)用nn_socktype->create()。這里找到的是nn_xpub_socktype,調(diào)用nn_xpub_create()。
  • 在nn_xpub_create()中,nn_xpub用自己的虛函數(shù)nn_xpub_sockbase_vfptr初始化nn_sockbase的虛函數(shù)表。

1.2 nn_bind()

nn_bind()根據(jù)指定的底層傳輸協(xié)議,初始化一系列底層對(duì)象,并把它們綁定到指定的地址上去。

int nn_bind (int s, const char *addr);

addr參數(shù)包括了協(xié)議類型和地址,如“ipc:///tmp/pubsub.ipc”,“ipc”是傳輸協(xié)議類型,“///tmp/pubsub.ipc”是地址。

這個(gè)過程中創(chuàng)建的對(duì)象包括:

  • nn_sock包括eps[]數(shù)組,數(shù)組中保存的nn_ep代表連接的endpoint,因此nn_sock支持多個(gè)連接。
  • nn_usock擁有原始socket。它引用nn_work,還定義了connecting, connected, accept, send, recv, stop等一系列任務(wù)。這些任務(wù)可以在nn_work的線程中異步執(zhí)行。
  • 在全局?jǐn)?shù)組nn_transports[]中保存了所有傳輸協(xié)議對(duì)象的創(chuàng)建信息nn_transport。nn_global_create_ep()根據(jù)調(diào)用者指定的傳輸協(xié)議類型,查找對(duì)應(yīng)的nn_transport。這里找到的是nn_ipc。
  • nn_ep調(diào)用nn_transport.bind()創(chuàng)建nn_bipc對(duì)象,這里是nn_ipc_bind()。nn_bipc保存在成員tran中。nn_bipc包括一個(gè)nn_usock實(shí)例,這個(gè)實(shí)例將被綁定在指定的地址上以便接受連接?!癰ipc”中的b像是“bound”的意思。
  • nn_bipc接受的連接保存在nn_aipc實(shí)例中,nn_bipc的aipcs[]數(shù)組可以保存多個(gè)實(shí)例。
  • nn_aipc也包括一個(gè)nn_usock,其中包括它自己的原始socket。nn_aipc的成員listener指向nn_bipc的nn_usock實(shí)例。nn_aipc調(diào)用nn_usock_swap_owner()接管listener,并調(diào)用accept()接受連接。“aipc”中的a像是“accepted”的意思。
  • nn_aipc包括一個(gè)nn_sipc實(shí)例。在原始socket配置完成后,后續(xù)工作將轉(zhuǎn)移到sipc上,nn_aipc的nn_usock也將被sipc接管?!皊ipc”中的s像是established或stream的意思。
    • nn_sipc包括一個(gè)nn_streamerhdr實(shí)例。nn_sipc委托nn_streamerhdr完成通信兩端的身份認(rèn)證工作,在這期間nn_usock將被nn_streamhdr托管。
    • nn_streamhdr包括一個(gè)nn_timer實(shí)例。后者將處理認(rèn)證超時(shí)的檢測(cè)工作。nn_timer也有一個(gè)nn_worker的引用,檢測(cè)工作是異步進(jìn)行的。

與client端連接完成后,還有一件事,就是關(guān)聯(lián)底層傳輸協(xié)議對(duì)象和上層協(xié)議對(duì)象,打通兩者之間的數(shù)據(jù)通道。這個(gè)通道就是nn_sipc的成員nn_pipebase。

  • nn_sipc初始化nn_pipebase時(shí),將自己的函數(shù)集(nn_sipc_pipebase_vfptr,包括發(fā)送和接收),綁定到nn_pipebase的vfptr成員上。
  • 調(diào)用nn_sockbase_ptr->add(),將nn_pipebase傳給nn_xpub,并保存在outpipes成員中。

2. Client端 (xsub)

2.1 nn_socket()

nn_socket()創(chuàng)建一個(gè)nn_sock。不同于Server端的是,nn_sock的nn_sockbase指針指向nn_xsub。

2.2 nn_setsockopt()

nn_setsockopt()設(shè)置nn_sock的選項(xiàng),這個(gè)選項(xiàng)針對(duì)底層的原始socket,也可能針對(duì)nn_xsub。比如,nn_xsub支持消息過濾,nn_sockopt()可以設(shè)置過濾條件。

2.3 nn_connect()

nn_connect()將根據(jù)指定的底層協(xié)議,初始化一系列的底層對(duì)象,并連接到指定地址的server端。

這個(gè)過程中創(chuàng)建的對(duì)象包括:

  • nn_sock包括eps[]數(shù)組。nn_ep創(chuàng)建nn_cipc,保存在成員tran中,這與server端不同。
  • nn_cipc包括nn_usock,其中包括它自己的原始socket。“cipc”中的c像是“connect”的意思。
  • nn_cipc包括一個(gè)nn_sipc。在nn_cipc的原始socket連接成功后,后續(xù)工作將轉(zhuǎn)移到sipc上,其nn_usock也被sipc接管。后面的工作就與server端的sipc一樣了。

與server端連接成功后,還要關(guān)聯(lián)底層傳輸協(xié)議對(duì)象和上層協(xié)議對(duì)象,這次sipc的成員nn_pipebase會(huì)連接到nn_xsub。

相關(guān)鏈接

nanomsg 1.1.5 源代碼分析 (一)
nanomsg 1.1.5 源代碼分析 (二)
nanomsg 1.1.5 源代碼分析 (三)
nanomsg 1.1.5 源代碼分析 (四)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容