最近调研了如何使用libuv
去监听nanomsg
的fd
,以下是一些关键技术点
获取真实fd
nn_socket
创建的返回值并不是真实系统的fd
,而是nanomsg
内部的数组序号。
如NN_MAX_SOCKETS
一般最大是512
个,则这里返回的就是第几个数组序号。
需要用如下方式获取真实fd
(以订阅为例),发布则将NN_RCVFD
换成NN_SNDFD
1 2 3 4
| int s = nn_socket(AF_SP, NN_SUB); int fd; size_t fd_len = sizeof(fd); nn_getsockopt(s, NN_SOL_SOCKET, NN_RCVFD, &fd, &fd_len);
|
订阅同一端口的多个消息
假如发布端是一个进程,发布两种话题topic1
和topic2
1 2 3 4 5 6
| int s = nn_socket(AF_SP, NN_PUB); const char buf1[] = "topic1|data_here"; const char buf2[] = "topic2|data_here"; nn_send(s, buf1, strlen(buf1), 0); sleep(1); nn_send(s, buf2, strlen(buf2), 0);
|
订阅端是另一个进程,同时订阅topic1
和topic2
订阅端正确做法是创建一个nn_socket
对象,然后调用nn_setsockopt
两次去过滤两个话题,如下
正确做法
1 2 3 4 5 6 7 8 9 10
| int s = nn_socket(AF_SP, NN_SUB); nn_setsockopt(s, NN_SUB, NN_SUB_SUBSCRIBE, "topic1", 6); nn_setsockopt(s, NN_SUB, NN_SUB_SUBSCRIBE, "topic2", 6);
# 这里根据上面的做法获取到订阅的真实fd
uv_poll_t poll_handle; uv_poll_init(XXX, &poll_handle, fd); uv_poll_start(&poll_handle, UV_READABLE, CallbackFunction); uv_run(XXX);
|
正确做法里,topic1
发布了,topic2
还未发布,则回调触发时能正确收到topic1
的数据
错误做法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int s1 = nn_socket(AF_SP, NN_SUB); nn_setsockopt(s1, NN_SUB, NN_SUB_SUBSCRIBE, "topic1", 6);
int s2 = nn_socket(AF_SP, NN_SUB); nn_setsockopt(s2, NN_SUB, NN_SUB_SUBSCRIBE, "topic2", 6);
# 这里根据上面的做法获取到订阅的真实fd1和fd2
uv_poll_t poll_handle_1; uv_poll_init(XXX, &poll_handle_1, fd1); uv_poll_start(&poll_handle_1, UV_READABLE, CallbackFunction1);
uv_poll_t poll_handle_2; uv_poll_init(XXX, &poll_handle_2, fd2); uv_poll_start(&poll_handle_2, UV_READABLE, CallbackFunction2); uv_run(XXX);
|
在这个错误做法里,如果topic1
发布了,topic2
还没发布,则CallbackFunction1
和CallbackFunction2
都会被调用
也就是任何一个话题发布,都会触发一遍所有回调
而正确做法里便不会出现问题