nanomsg源码阅读(一)

框架简介

nanomsgzeromq作者Martin Sustrik用C重写的一套具有可扩展协议的一套通信框架,具体nanomsg与zeromq的不同与改进之处及为什么要用C重写在这里有详细的描述,个人感觉C的代码风格和目录结构组织都看着舒服多了,:),另外Martin Sustrik博客(http://250bpm.com/ )里面的每篇文章感觉都挺不错的,推荐关注订阅!

因为nanomsg还处于开发测试阶段,代码量还不是十分庞大,文档和注释也不够全面,于是想通过这一系列博客,一方面记录下我对nanomsg当前源码(https://github.com/250bpm/nanomsg)的阅读过程,同时也学习下一个好的开源项目的代码组织及开发过程。

源码组织

首先看下nanomsg的src目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
nn.h*                 // nanomsg对外暴露的接口api
transport.h* // 通信层定义,,目的应该是想暴露给用户以实现可扩展,但目前还包含utils下头文件……
inproc.h* // 一种transport,安装到include/nanomsg下
ipc.h* // 一种transport,安装到include/nanomsg下
tcp.h* // 一种transport,安装到include/nanomsg下
protocol.h* // 协议层定义,目的应该是想暴露给用户以实现可扩展,但目前还包含utils下头文件……
reqrep.h* // 一种protocol,安装到include/nanomsg下
pubsub.h* // 一种protocol,安装到include/nanomsg下
bus.h* // 一种protocol,安装到include/nanomsg下
pair.h* // 一种protocol,安装到include/nanomsg下
pipeline.h* // 一种protocol,安装到include/nanomsg下
survey.h* // 一种protocol,安装到include/nanomsg下
utils/ // 实用工具包,包含基本数据结构(list,queue,hash)互斥及原子操作(mutex,atomic)等
transports/ // 通信层实现,包括(inproc:进程内通信;ipc:进程间通信;tcp:tcp通信)
protocols/ // 协议层实现,包括(REQ/REP:请求/应答;PUB/SUB:发布订阅等.)
core/ // generic code,glue between the pieces
aio/ // 线程池模拟的异步操作,带状态机的事件驱动
CMakeLists.txt* // cmake编译文件
pkgconfig.in* // pkconfig工具配置文件
README* // readme

其中nanomsg对外暴露的接口api定义在nn.h中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
NN_EXPORT int nn_socket (int domain, int protocol);
NN_EXPORT int nn_close (int s);
NN_EXPORT int nn_setsockopt (int s, int level, int option,
const void *optval, size_t optvallen);
NN_EXPORT int nn_getsockopt (int s, int level, int option,
void *optval, size_t *optvallen);
NN_EXPORT int nn_bind (int s, const char *addr);
NN_EXPORT int nn_connect (int s, const char *addr);
NN_EXPORT int nn_shutdown (int s, int how);
NN_EXPORT int nn_send (int s, const void *buf, size_t len, int flags);
NN_EXPORT int nn_recv (int s, void *buf, size_t len, int flags);
NN_EXPORT int nn_sendmsg (int s, const struct nn_msghdr *msghdr, int flags);
NN_EXPORT int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags);
NN_EXPORT int nn_device (int s1, int s2);

熟悉posix socket接口api的人应该对这些接口不陌生(除了后面三个函数,以后会介绍), 所以一个简单的服务端应答程序大致是这样的:

1
2
3
4
5
6
char buf[10];
int s = nn_socket(AF_SP, NN_REP);
nn_bind(s, "tcp://*:5555");
nn_recv(s, buf, 10, 0);
nn_send(s, "World", 5, 0);
nn_close(s);

对应的客户端请求程序大致为:

1
2
3
4
5
6
7
char buf[10];
int s = nn_socket(AF_SP, NN_REQ);
nn_connect(s, "tcp://localhost:5555");
nn_send(s, "Hello", 5, 0);
nn_recv(s, buf, 10, 0);
printf("Hello %sn", buf);
nn_close(s);

敬请期待

对nanomsg接口及代码框架了解后,不妨让我们深入下细节,探探究竟。

下一篇文章将深入实用工具类包utils内部,看看nanomsg都需要哪些基础功能?以及如何包装的?

敬请期待~