Post

ZeroMQ通信时延测试

ZeroMQ通信时延测试

1 原理

Publisher发送时间戳,Subscriber接收时间戳,计算时间差。 实验环境:Ubuntu 22.04 x64, 编译之前需要安装ZMQ库:sudo apt install libzmq3-dev

2 代码

2.1 pub.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

int main() {
    void *context = zmq_ctx_new();
    void *publisher = zmq_socket(context, ZMQ_PUB);
    
    // 绑定到 TCP 端口 5555
    int rc = zmq_bind(publisher, "tcp://*:5555");
    if (rc != 0) {
        perror("zmq_bind failed");
        return -1;
    }

    while (1) {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);

        const char *message_format = "%ld.%09ld";
        char message[50];
        snprintf(message, sizeof(message), message_format, ts.tv_sec, ts.tv_nsec);

        zmq_send(publisher, message, strlen(message), 0);
        printf("Publisher sent: %s\n", message);
        sleep(1); // 模拟间隔时间
    }

    zmq_close(publisher);
    zmq_ctx_destroy(context);

    return 0;
}

2.2 sub.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <zmq.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <string.h>

int main() {
    void *context = zmq_ctx_new();
    void *subscriber = zmq_socket(context, ZMQ_SUB);

    // 连接到发布者
    int rc = zmq_connect(subscriber, "tcp://localhost:5555");
    if (rc != 0) {
        perror("zmq_connect failed");
        return -1;
    }

    // 订阅所有消息(空字符串表示所有主题)
    zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);

    while (1) {
        char buffer[256] = {0};
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        zmq_recv(subscriber, buffer, sizeof(buffer), 0);
        // 记录当前时间
        struct timespec ts_recv;
        clock_gettime(CLOCK_REALTIME, &ts_recv);

        printf("Subscriber received: %s\n", buffer);

        // 解析接收到的消息中的时间戳
        char *time_str = strtok(buffer, ".");
        if (time_str == NULL) {
            printf("Invalid message format\n");
            continue;
        }
        long sec = atol(time_str);
        time_str = strtok(NULL, "");
        if (time_str == NULL) {
            printf("Invalid message format\n");
            continue;
        }
        long nsec = atol(time_str);

        // 构建接收时间的时间戳
        struct timespec ts_sent = {sec, nsec};

        // 计算时间差
        long time_diff_ns = (ts_recv.tv_sec - ts_sent.tv_sec) * 1000000000 + (ts_recv.tv_nsec - ts_sent.tv_nsec);
        printf("Time difference: %ld ns\n", time_diff_ns);
    }

    zmq_close(subscriber);
    zmq_ctx_destroy(context);
    return 0;
}

2.3 Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 目标文件
PUB = pub
SUB = sub

# 源文件
SRCS_PUB = pub.c
SRCS_SUB = sub.c

# 编译器和选项
CC = $(CROSS_COMPILE)gcc
CFLAGS = -lzmq

# 默认目标
all: $(PUB) $(SUB)

# $(CFLAGS)必须在最后
# 编译 pub
$(PUB): $(SRCS_PUB)
	$(CC) -o $@ $^ $(CFLAGS)

# 编译 sub
$(SUB): $(SRCS_SUB)
	$(CC) -o $@ $^ $(CFLAGS)

# 清理生成的文件
clean:
	rm -f $(PUB) $(SUB)

3 结果示例

3.1 Publisher

1
2
3
4
user@user:~/Work/12-2024/zmq_test$ ./pub 
Publisher sent: 1734446775.086033816
Publisher sent: 1734446776.086658492
Publisher sent: 1734446777.087206004

3.2 Subscriber

1
2
3
4
5
6
7
user@user:~/Work/12-2024/zmq_test$ ./sub 
Subscriber received: 1734446778.087726464
Time difference: 161106 ns
Subscriber received: 1734446779.088250488
Time difference: 437945 ns
Subscriber received: 1734446780.088922319
Time difference: 671090 ns

注:ARM端编译出错,待解决…

1
2
3
4
5
6
aarch64-openeuler-linux-gcc -o pub pub.c -lzmq
pub.c:1:10: fatal error: zmq.h: No such file or directory
    1 | #include <zmq.h>
      |          ^~~~~~~
compilation terminated.
make: *** [Makefile:19:pub] 错误 1
This post is licensed under CC BY 4.0 by the author.