ZMQ 握手过程解析

来源:互联网 发布:ubuntu使用wine 编辑:程序博客网 时间:2024/06/04 23:46


ZMQ是一种开源的消息机制,具有一定的性能。科普资料大家可以自己看看,或者进入官网拿源码研究。

本文主要解析ZMQ的握手过程,所以从server端bind 之后,client端connect之时说起。

话说server端bind之后,它向socket一样在那对指定地址的端口进行listen的,此时server端还没有创建必须的通信设施,如session,engine等。只有在client端连接上来之后,被server端accept时,它才会为这个连接创建基本的通信设施。换句话说,server端此时在等待它的(listener) in_event(),也就是上图中的[1],黄色的小圈(可以视为listener对应的pollset,或者通俗的就认为是poller)。

花开两朵,各表一枝。此时,client端还是创世纪(connect),构件它的基础通信设施,依次为:session,pipe(pair),connecter,engine。在将engine  plug到io thread之后将迎来client端engine的第一次 event。(该处有两个地方需要特别关注的:其一为client端将connecter给shutdown了,它将底层的socket句柄交给了engine,完成了使命;其二为在同步?调用in_event时,set pollin &pollout)

在首次的in_event时开始了正式的 handshake。在client端进行handshake中,因为双方还没建立通道,是读不出数据的,所以client端handshake第一次失败,即为图中第一条点划线箭头。

由于client端的尝试通信,触发了server端的in_event,即server端的[2],它其实是listener的。(不知道TCP三次握手在里面的时序)此时listener开始为accept到的连接创建通信设施,依次为:engine,session,准备将session  attach到engine上(不知道方向有没有搞错,夜里昏沉),即server端的[3]……停!!!!!

就在这些必要的通信设施创建完成的时刻,client端有动作了,它的out_event被触发了,即client端的[2]。(有一个关键点,out_event是怎样被触发的)此时它要开始装填handshake的greeting  frame,即为client端的第一条短水平线(图中位置不对)。(知识点:ZMQ的greeting frame由12字节构成:帧头0xff + 8字节id长度? + 0x7f + Version + socket type)开始是只装填10字节的,此时还没handshake 成功。

忘了告诉说,其实通信设施还没创建完成,对比一下也是知道的。由于ZMQ内部消息是异步的,所以要等待client端释放资源才能做接下来的事情。server端继续创建pipe(pair),并将engine plug 到 io thread上,即server端的[3]~[4]。此时,它也是要去尝试handshake的。在handshake中,server端读到了刚才client发过来的10字节,10字节是不够的所以,要继续读,因为client端没有数据了,所以读出0字节,并返回。server端handshake也失败。(此处有一点不通,暂不表)

来而不往非礼也,server端此时也触发了out event,即server端的[5]。(特别注意,此处的pollset的sink不是listener了而是engine)在此过程中server端装填了12字节的greeting frame。

client端说终于来了,我等的好辛苦,即client端[3]。client端一下子接收了完整的greeting frame,诸事顺利,它将装填余下的两字节greeting frame,即client端第二条短水平线。此时 client端handshake成功!同时创建了余下的通信设施:encoder/decoder。继续在client端的in event里,终于可以用decoder了。它会使用session去push异步发送来的message,并将它push到pipe里供socket base取用。可惜,此时socket kernel buffer 空空如也。

装填了就要发送,client 端out event再次被唤起,即client端[5]。

之后,client端继续out event,[6]。encoder终于可以使用,它通过session从pipe里面pull消息来发送。不同type的不一样,dealer会涉及到identity,所以会是identity。如果没有identity的将是一个0帧。并将其发送到了对方(server端)的socket kernel buffer里。

server端要抱怨了一个问候还要分两次,终于等到了([6]),server端handshake成功,并创建encoder/decoder。这事儿还没完,server端在in event里继续使用decoder去刨数据,一发现,还真有,identity或者0帧,不过有被丢弃的可能,[7]。

此时,client端的out event又被唤起了,怎么阴魂不散!此时,它也用encoder去pipe里刨数据,落空了,所以就reset pollout。它的 out event 终于可以滚蛋了,图中第一条红箭头。

刚说client端的out event滚蛋了,server端的不甘寂寞,唤醒它的out event来亮亮相。encoder也创建了,此时不用待何时。拿着就去pipe里面刨数据,可惜也没刨出来什么。发了一个0帧过去。等待,图中怎么是2 字节?弄错了? 自己看encoder/decoder去吧!此是为server端[8]。

有出就有入,client端触发in event,接收这个数据,0帧,参见session_base_t::pull_msg()。是为client端[8]。

server端的[9]和红箭头参考client端。

至此,handshake全程结束。


收拾收拾,下班。凌乱之言,仅供参考。

期待和大家一起讨论ZMQ。

0 0