ZMQ:"Resource temporarily unavailable" 连接 zmq 套接字时
ZMQ: "Resource temporarily unavailable" when connecting zmq socket
我正在尝试通过 czmqz (4.0.2) 使用 libzmq (4.2.2) 在 Python 程序和我的 C++ 应用程序之间建立 IPC 通信通道。
我正在使用 ZMQ publisher/subscriber 模式,其中 Python 程序绑定到端口并使用 pyzmq (16.0.2) 发布消息,而我的 C++ 程序使用 zsock class 从 CZMQ 以订阅者身份连接。
问题是,每当我的订阅者尝试连接时,我都会收到错误代码 11,资源暂时不可用。奇怪的是,这个系统似乎在我的开发机器上工作得很好,但在我部署到的目标系统上却不行。
问题出现在以下简化方法中初始化套接字的第一行:
bool ZmqSocketWrapper::connectSubscriber(string address)
{
m_address = address;
m_pSocket = zsock_new_sub(address.c_str(), "");
int errorCode = zmq_errno();
if (errorCode != 0)
{
printf(zmq_strerror(errorCode));
return false;
}
return true;
}
调用如下:
m_subscriberSocket->connectSubscriber("tcp://127.0.0.1:5555");
我也尝试了其他变体,结果相同:
m_subscriberSocket->connectSubscriber("tcp://localhost:23232");
m_subscriberSocket->connectSubscriber("ipc:///tmp/test");
在网上搜索时,似乎大多数其他人在尝试 send/receive 时都遇到了这个问题,所以我在尝试打开插座时遇到这个问题似乎很奇怪。
其他一些细节:
- 我的 ZMQ 发布器是使用 pyzmq 在 Python 中编写的,并且在同一目标系统上工作正常,这表明问题出在 czmq。
- 我遇到问题的机器是 Raspberry Pi,以防相关,但请记住以上几点。
- 不,没有其他东西在使用该端口,我已经使用 netstat 确认服务器端口正在侦听。
- 是的,我已经尝试 运行 我的客户端作为 root。
非常感谢任何帮助!
好消息是纯pyzmq
场景运行良好,
硬件或 O/S 相关问题似乎已从故障列表中排除。
该死的绑定 (盲目用户程序由 "high-level" 倾斜抽象)
首先是,
一些高级实业家提倡从 native-API 中删除用户端选项。
例如,CZMQ 这样做是因为它假设 每个 SUB
端想要 只是 .connect()
, 不留下相反的 .bind()/.connect()
选项可用。老好 ZeroMQ API 总是让用户有这个选择,这是公平的。同样,在设置套接字连接之前需要设置许多性能调整变量,这使得"high-level"绑定对于分布式系统实现来说更加麻烦。
接下来是奇怪的事情,代码 运行 在一个盒子上很好,在另一个盒子上却不行。
我担心的是用户端有责任将 LINGER
设置为零 + .close()
任何此类创建的 SUB
套接字(如果没有适当的异常处理,则不需要发生在 zmq.Context()
实例安全 .term()
之前。这可能会挂起孤儿,后来导致实际资源(仍然)被占用,导致 errno
代码 11,Resource temporarily unavailable.
最后但同样重要的是 - 资源不是 consumables/disposables
建议的代码无法更好地展示此类资源低效行为,并且会累积每次调用的所有设置/配置/拆卸开销成本。这是一个非常糟糕的设计实践(虽然用户可能会在许多 "schoolbook"-examples 中遇到它)。如果对高效分布式计算参数的更多细节感兴趣,也与此相关,
bool ZmqSocketWrapper::connectSubscriber(string address)
{ b_RetFLAG = true;
m_address = address;
m_pSocket = zsock_new_sub(address.c_str(), "");
int errorCode = zmq_errno();
if (errorCode != 0)
{
printf(zmq_strerror(errorCode));
b_RetFLAG = false;
}
// -------------------------------------------------------------
zsock_destroy( &m_pSocket ); // USER's MANDATORY DUTY PRE-RET
// -------------------------------------------------------------
return b_RetFLAG;
}
如果确实遇到麻烦,
使用本机 API,您的代码完全控制舞台。
我正在尝试通过 czmqz (4.0.2) 使用 libzmq (4.2.2) 在 Python 程序和我的 C++ 应用程序之间建立 IPC 通信通道。
我正在使用 ZMQ publisher/subscriber 模式,其中 Python 程序绑定到端口并使用 pyzmq (16.0.2) 发布消息,而我的 C++ 程序使用 zsock class 从 CZMQ 以订阅者身份连接。
问题是,每当我的订阅者尝试连接时,我都会收到错误代码 11,资源暂时不可用。奇怪的是,这个系统似乎在我的开发机器上工作得很好,但在我部署到的目标系统上却不行。
问题出现在以下简化方法中初始化套接字的第一行:
bool ZmqSocketWrapper::connectSubscriber(string address)
{
m_address = address;
m_pSocket = zsock_new_sub(address.c_str(), "");
int errorCode = zmq_errno();
if (errorCode != 0)
{
printf(zmq_strerror(errorCode));
return false;
}
return true;
}
调用如下:
m_subscriberSocket->connectSubscriber("tcp://127.0.0.1:5555");
我也尝试了其他变体,结果相同:
m_subscriberSocket->connectSubscriber("tcp://localhost:23232");
m_subscriberSocket->connectSubscriber("ipc:///tmp/test");
在网上搜索时,似乎大多数其他人在尝试 send/receive 时都遇到了这个问题,所以我在尝试打开插座时遇到这个问题似乎很奇怪。
其他一些细节:
- 我的 ZMQ 发布器是使用 pyzmq 在 Python 中编写的,并且在同一目标系统上工作正常,这表明问题出在 czmq。
- 我遇到问题的机器是 Raspberry Pi,以防相关,但请记住以上几点。
- 不,没有其他东西在使用该端口,我已经使用 netstat 确认服务器端口正在侦听。
- 是的,我已经尝试 运行 我的客户端作为 root。
非常感谢任何帮助!
好消息是纯pyzmq
场景运行良好,
硬件或 O/S 相关问题似乎已从故障列表中排除。
该死的绑定 (盲目用户程序由 "high-level" 倾斜抽象)
首先是,
一些高级实业家提倡从 native-API 中删除用户端选项。
CZMQ 这样做是因为它假设 每个 SUB
端想要 只是 .connect()
, 不留下相反的 .bind()/.connect()
选项可用。老好 ZeroMQ API 总是让用户有这个选择,这是公平的。同样,在设置套接字连接之前需要设置许多性能调整变量,这使得"high-level"绑定对于分布式系统实现来说更加麻烦。
接下来是奇怪的事情,代码 运行 在一个盒子上很好,在另一个盒子上却不行。
我担心的是用户端有责任将 LINGER
设置为零 + .close()
任何此类创建的 SUB
套接字(如果没有适当的异常处理,则不需要发生在 zmq.Context()
实例安全 .term()
之前。这可能会挂起孤儿,后来导致实际资源(仍然)被占用,导致 errno
代码 11,Resource temporarily unavailable.
最后但同样重要的是 - 资源不是 consumables/disposables
建议的代码无法更好地展示此类资源低效行为,并且会累积每次调用的所有设置/配置/拆卸开销成本。这是一个非常糟糕的设计实践(虽然用户可能会在许多 "schoolbook"-examples 中遇到它)。如果对高效分布式计算参数的更多细节感兴趣,也与此相关,
bool ZmqSocketWrapper::connectSubscriber(string address)
{ b_RetFLAG = true;
m_address = address;
m_pSocket = zsock_new_sub(address.c_str(), "");
int errorCode = zmq_errno();
if (errorCode != 0)
{
printf(zmq_strerror(errorCode));
b_RetFLAG = false;
}
// -------------------------------------------------------------
zsock_destroy( &m_pSocket ); // USER's MANDATORY DUTY PRE-RET
// -------------------------------------------------------------
return b_RetFLAG;
}
如果确实遇到麻烦,
使用本机 API,您的代码完全控制舞台。