c - 断开 ZeroMQ 套接字和 ZMQ_EVENT_DISCONNECTED
问题描述
ZeroMQ API 文档指出该事件(来源此处):
ZMQ_EVENT_DISCONNECTED
套接字意外断开。事件值是底层网络套接字的 FD。警告:此套接字将被关闭。
此处如何定义“意外”,以及如何触发“干净”断开连接,例如REQ
-REP
对?
我试过了:
zmq_close(client)
信号ZMQ_EVENT_DISCONNECTED
,虽然我原以为这是干净的zmq_disconnect(client, addr)
在上述不改变监控事件之前(即,当显式断开连接成功时,我仍然收到“意外断开连接”的信号)
有没有办法区分干净的套接字关闭和kill -9
客户端上的 a ?(后者还是有信号的FIN
,所以理论上这应该是可以检测和区分的)
下面的说明代码(从这里修改;编译和运行gcc -lzmq zmq_test.c && ./a.out
)
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <zmq.h>
// Read one event off the monitor socket; return value and address
// by reference, if not null, and event number by value. Returns -1
// in case of error.
static int get_monitor_event (void *monitor, int *value, char **address)
{
// First frame in message contains event number and value
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor, 0) == -1)
return -1; // Interruped, presumably
assert (zmq_msg_more (&msg));
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
uint16_t event = *(uint16_t *) (data);
if (value)
*value = *(uint32_t *) (data + 2);
// Second frame in message contains event address
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor, 0) == -1)
return -1; // Interruped, presumably
assert (!zmq_msg_more (&msg));
if (address) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*address = (char *) malloc (size + 1);
memcpy (*address, data, size);
*address [size] = 0;
}
printf("event: %d\n", event);
return event;
}
static void close_zero_linger(void *socket)
{
int linger = 0;
zmq_setsockopt(socket, ZMQ_LINGER, &linger, sizeof(linger));
zmq_close(socket);
}
static void bounce(void *client, void *server)
{
char send_buf[] = "Hello";
char recv_buf[sizeof(send_buf) / sizeof(send_buf[0])];
zmq_send(client, send_buf, sizeof(send_buf), 0);
zmq_recv(server, recv_buf, sizeof(recv_buf), 0);
zmq_send(server, send_buf, sizeof(send_buf), 0);
zmq_recv(client, recv_buf, sizeof(recv_buf), 0);
}
int main (void)
{
void *ctx = zmq_ctx_new ();
void *client = zmq_socket (ctx, ZMQ_REQ);
void *server = zmq_socket (ctx, ZMQ_REP);
int rc = zmq_socket_monitor (client, "tcp://127.0.0.1:9999", 0);
// Monitor all events on client and server sockets
rc = zmq_socket_monitor (server, "inproc://monitor-server", ZMQ_EVENT_ALL)
void *server_mon = zmq_socket (ctx, ZMQ_PAIR);
rc = zmq_connect (server_mon, "inproc://monitor-server");
// Now do a basic ping test
rc = zmq_bind (server, "tcp://127.0.0.1:9998");
rc = zmq_connect (client, "tcp://127.0.0.1:9998");
bounce (client, server);
// Close client
rc = zmq_disconnect(client, "tcp://127.0.0.1:9998");
printf("disconnect: %d\n", rc);
// close_zero_linger (client);
rc = zmq_close(client);
printf("close: %d\n", rc);
// sleep(1); // no difference
// This is the flow of server events
event = get_monitor_event (server_mon, NULL, NULL);
assert (event == ZMQ_EVENT_LISTENING);
event = get_monitor_event (server_mon, NULL, NULL);
assert (event == ZMQ_EVENT_ACCEPTED);
event = get_monitor_event (server_mon, NULL, NULL);
assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
// sleep(1); // no difference
event = get_monitor_event (server_mon, NULL, NULL);
// assert (event == ZMQ_EVENT_CLOSED);
// event = get_monitor_event (server_mon, NULL, NULL);
// assert (event == ZMQ_EVENT_MONITOR_STOPPED);
assert (event == ZMQ_EVENT_DISCONNECTED); // why??
// Close down the sockets
close_zero_linger (server);
close_zero_linger (server_mon);
zmq_ctx_term (ctx);
return 0;
}
解决方案
推荐阅读
- c# - C#如何安全地存储不变的密码?
- apache-kafka - Telegraf x509 输入以监控 Kafka SSL 端点
- html - 如何从 iFrame 中显示全屏覆盖?
- c# - 如何使外部程序窗口高于屏幕尺寸?
- django - 在 uwsgi 2.0.18 和 python 3.6.9 中无法使用编码错误启动 uwsgi
- java - Gradle 下载不需要的依赖项
- python - 是否可以在不使用 Else 的情况下仅使用 Try 或使用条件来捕获错误并执行代码?
- python - 有没有办法用单索引数据帧划分多索引数据帧?
- docker - 将 Flutter ui 测试与 docker 集成:在 headless chrome 上进行驱动测试
- python - 关于字符串索引的简单Python问题