zmq源码阅读 —— zmq_send()和zmq_recv()

本文详细解析了ZeroMQ(ZMQ)库中消息的接收与发送过程,包括zmq_recv与zmq_send函数的具体实现细节。展示了如何利用ZMQ进行高效的消息传递,并提供了关键步骤的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

int zmq_recv (void *s_, void *buf_, size_t len_, int flags_)
{
    if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
        errno = ENOTSOCK;
        return -1;
    }
    zmq_msg_t msg; // 创建消息结构
    int rc = zmq_msg_init (&msg); // 初始化空消息
    errno_assert (rc == 0);

    zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
    int nbytes = s_recvmsg (s, &msg, flags_); // 接收消息
    if (unlikely (nbytes < 0)) {
        int err = errno;
        rc = zmq_msg_close (&msg);
        errno_assert (rc == 0);
        errno = err;
        return -1;
    }

    //  At the moment an oversized message is silently truncated.
    //  TODO: Build in a notification mechanism to report the overflows.
    size_t to_copy = size_t (nbytes) < len_ ? size_t (nbytes) : len_; //计算消息大小
    memcpy (buf_, zmq_msg_data (&msg), to_copy); // 通过zmq_msg_data()获得消息的data地址,拷贝到buf_中

    rc = zmq_msg_close (&msg); // 释放或销毁消息
    errno_assert (rc == 0);

    return nbytes;
}
---------------------------------------------------------------------
int zmq_recvmsg (void *s_, zmq_msg_t *msg_, int flags_)
{
    return zmq_msg_recv (msg_, s_, flags_);
}
----------------------------------------------------------------------
int zmq_msg_recv (zmq_msg_t *msg_, void *s_, int flags_)
{
    if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
        errno = ENOTSOCK;
        return -1;
    }
    zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
    int result = s_recvmsg (s, msg_, flags_);
    return result;
}
-----------------------------------------------------------------------
static int
s_recvmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_)
{
    int rc = s_->recv ((zmq::msg_t*) msg_, flags_); 
    if (unlikely (rc < 0))
        return -1;
    return (int) zmq_msg_size (msg_);// 计算消息的大小
}
---------------------------------------------------------------------------------
=================================================================================
---------------------------------------------------------------------------------
int zmq_send (void *s_, const void *buf_, size_t len_, int flags_)
{
    if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
        errno = ENOTSOCK;
        return -1;
    }
    zmq_msg_t msg; // 创建消息结构
    int rc = zmq_msg_init_size (&msg, len_); // 以buf长度初始化成消息
    if (rc != 0)
        return -1;
    memcpy (zmq_msg_data (&msg), buf_, len_); // 将buf的内容拷贝给消息

    zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
    rc = s_sendmsg (s, &msg, flags_); // 发送消息
    if (unlikely (rc < 0)) {
        int err = errno;
        int rc2 = zmq_msg_close (&msg); // 释放和销毁消息
        errno_assert (rc2 == 0);
        errno = err;
        return -1;
    }
    
    //  Note the optimisation here. We don't close the msg object as it is
    //  empty anyway. This may change when implementation of zmq_msg_t changes.
    return rc;
}

从注释中可以看出消息发送的流程,czmq,jzmq等已经做了封装,也可以自己做封装。

### 关于 Dart 中 `zmq_msg_recv` 的使用 在 Dart 编程语言中,`zmq_msg_recv` 并不是一个原生支持的功能。该函数通常来源于 ZeroMQ 库中的 C API,在 C 或其他低级语言中有更广泛的使用场景。然而,通过 FFI (Foreign Function Interface),可以将此功能引入到 Dart 中并实现跨平台通信。 以下是关于如何在 Dart 中调用 `zmq_msg_recv` 函数的一个示例说明: #### 配置环境 为了能够在 Dart 中使用 `zmq_msg_recv`,需要先安装 libzmq 库以及对应的 Dart 包绑定工具,例如 `dart_zmq` 或者手动配置 FFI 调用接口[^1]。 #### 示例代码 下面是一个简单的例子展示如何利用 Dart FFI 来调用 `zmq_msg_recv`: ```dart import 'dart:ffi'; import 'package:ffi/ffi.dart'; // 假设已经加载了 libzmq.so 动态库 final DynamicLibrary zmqLib = DynamicLibrary.open('libzmq.so'); void main() { final Pointer<Uint8> msgPtr = allocate(count: 256); // 分配内存用于接收消息 try { int result = zmqMsgRecv(msgPtr, socketPointer, flags); if (result != -1) { // 成功接收到数据 String message = Utf8.fromUtf8(msgPtr.cast<Utf8>()); print('Received Message: $message'); } else { throw Exception('Failed to receive message.'); } } finally { free(msgPtr); // 清理分配的内存资源 } } /// 定义 zmq_msg_recv 方法签名 typedef ZmqMsgRecvNative = Int32 Function(Pointer<Uint8>, Pointer<Void>, Int32); typedef ZmqMsgRecvDart = int Function(Pointer<Uint8>, Pointer<Void>, int); final zmqMsgRecv = zmqLib.lookupFunction< ZmqMsgRecvNative, ZmqMsgRecvDart>('zmq_msg_recv'); ``` 上述代码片段展示了如何定义外部函数指针,并通过它来调用实际的 C 函数 `zmq_msg_recv`[^2]。注意这里假设存在一个有效的套接字实例 (`socketPointer`) 及其标志位参数 (`flags`)。 #### 参数解释 - **msg_ptr**: 指向存储接收到的消息缓冲区地址。 - **socket**: 表示已初始化好的 ZeroMQ Socket 对象句柄。 - **flags**: 控制行为选项,比如是否阻塞等待等。 以上就是有关 Dart 下使用 `zmq_msg_recv` 的基本介绍及其简单应用案例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值