有人遇到过nn_poll()返回误报的问题吗? 我们以某种非常规的方式与中间经纪人建立了一个非常简单的pub sub,因为我们想减少损失: 发布者-> PUSH->拉->经纪人-> PUB->订阅者 这看起来很有希望,但是有一个小缺点,就是我们总是让nn_poll错误地报告在不应该存在的情况下存在数据。 我们构建了一个小型测试应用程序,该应用程序可以100%复制该代码-有人可以看到我们做错了吗? 该测试首先在后台运行代理,然后是恰好需要2条消息的订户,然后在任何时间点,我们都可以启动发布者,发送2条消息然后退出。
经纪人代码 代理很简单-使用PULL套接字可以接收来自所有发布者的出版物(并且由于只有一个代理,因此同一代理将接收到每个消息,因此使用PUSH / PULL不会出现问题)。 出于某种原因,尝试连接PULL <-> PUB时nn_device失败(或者可能是我们看到的问题的提示?)
static constexpr const char* kSubAddr = "ipc://tmp/subscribers";
static constexpr const char* kPubAddr = "ipc://tmp/publishers";
const char *data[] = {"AAAAA:1234567890", "BBBBB:0987654321"};
const char *topic[] = {"AAAAA", "BBBBB"};
void broker()
{
int pub, pull, rc;
pull = nn_socket (AF_SP, NN_PULL);
mapf_assert(pull >= 0);
rc = nn_bind(pull, kPubAddr);
mapf_assert(rc);
pub = nn_socket (AF_SP, NN_PUB);
mapf_assert(pub);
rc = nn_bind (pub, kSubAddr);
nn_pollfd item = {pull, NN_POLLIN, 0};
while(1)
{
rc = nn_poll(&item, 1, -1);
mapf_assert(rc == 1);
char buf[256] = {0};
rc = nn_recv(pull, buf, 256, 0);
std::cout << "broker: received " << rc << " bytes: " << buf << std::endl;
int size = rc;
rc = nn_send(pub, buf, rc, 0);
std::cout << "broker: sent " << rc << " bytes: " << buf << std::endl;
mapf_assert(rc == size);
}
}
**订户代码** 订阅者有2个SUB套接字,每个SUB套接字都订阅了一个不同的主题。 它使用无超时的nn_poll()来检查两个套接字是否已准备好数据,然后读取该数据。 然后,它会以较短的超时时间运行另一个nn_poll()并声明,因为其中一个套接字被标记为它具有不应该存在的数据。
void subscriber()
{
int rc, sub[2];
for (int i = 0; i < 2; i++) {
std::cout << "sub: " << i << ": Connect " << kSubAddr << " subscribe " << topic[i] << std::endl;
sub[i] = nn_socket(AF_SP, NN_SUB);
mapf_assert(sub[i] >= 0);
rc = nn_connect(sub[i], kSubAddr);
mapf_assert(rc > 0);
rc = nn_setsockopt(sub[i], NN_SUB, NN_SUB_SUBSCRIBE, topic[i], 5);
mapf_assert(rc == 0);
}
nn_pollfd items[2] = {
{sub[0], NN_POLLIN, 0},
{sub[1], NN_POLLIN, 0},
};
int num_events = 0;
std::cout << "sub: polling" << std::endl;
do {
num_events = nn_poll(items, 2, -1);
} while (num_events != 2);
std::cout << "sub: try receive from both sockets" << std::endl;
for (int i = 0; i < 2; i++) {
char buf[256] = {0};
rc = nn_recv(sub[i], buf, 256, 0);
std::cout << "sub: received " << buf << " from socket " << i << std::endl;
}
num_events = nn_poll(items, 2, 100);
mapf_assert(num_events == 0);
}
发布者代码 发布者使用PUSH套接字连接到发布者端点,然后发送2条消息,每个消息都有不同的主题。
void publisher()
{
int pub = nn_socket(AF_SP, NN_PUSH);
mapf_assert(pub >= 0);
std::cout << "pub: connect " << kPubAddr << std::endl;
int rc = nn_connect(pub, kPubAddr);
for (int i = 0; i < 2; i++) {
std::cout << "pub: send " << data[i] << std::endl;
rc = nn_send(pub, data[i], strlen(data[i]), 0);
mapf_assert(rc == (int)strlen(data[i]));
sleep(1);
}
}
这是输出:
[1]$ ./test b &
[2]$ ./test s &
sub: 0: Connect ipc:///tmp/tbeliyah/subscribers subscribe AAAAA
sub: 1: Connect ipc:///tmp/tbeliyah/subscribers subscribe BBBBB
sub: polling
[]$ ./test p
pub: connect ipc:///tmp/tbeliyah/publishers
pub: send AAAAA:1234567890
broker: received 16 bytes: AAAAA:1234567890
broker: sent 16 bytes: AAAAA:1234567890
sub: try receive from both sockets
sub: received AAAAA:1234567890 from socket 0
pub: send BBBBB:0987654321
broker: received 16 bytes: BBBBB:0987654321
broker: sent 16 bytes: BBBBB:0987654321
sub: received BBBBB:0987654321 from socket 1
Assertion failed: num_events == 0 (/********/test.cpp:72)
[2]+ Aborted (core dumped) ./test s