zeromq / cppzmq

Header-only C++ binding for libzmq
http://www.zeromq.org
MIT License
1.93k stars 757 forks source link

when i send it will show "Resource temporarily unavailable" #548

Open adadKKKX opened 2 years ago

adadKKKX commented 2 years ago

Hello. i'm using req/resp.

Env

it works on windows10 (req) & Ubuntu Port Binoic (Resp) (armv8) the same code is worked on yesterday .but now it does not work. ,the zppzmq version is same 425

Problem

when i send ,it return "Resource temporarily unavailable" all device

Code

protobuf script

https://paste.ubuntu.org.cn/4545606

Req


zmq::context_t context(1);

zmq::socket_t  Reqer(context, zmq::socket_type::req);

void NetServer::TNetStart(u_short *port)
{
    //CLog netlog = Settings::GetInstance()->Logger_NetWork;

    auto Req
        = std::make_shared<NetMsg::ReqHeader>();

    auto Cor
        = std::make_shared<NetMsg::PubSub_Coordinate>();
    //spy all events

    std::cout << std::get<0>(zmq::version()) << std::endl;
    std::cout << std::get<1>(zmq::version()) << std::endl;
    std::cout << std::get<2>(zmq::version()) << std::endl;
   // netlog.printf("[%s:%d]NetServer::TNetStart zmq->subscriber", __FILE__, __LINE__);
    //netlog.printf("binding local 1025");
    try
    {
        Reqer.connect("tcp://192.168.191.2:1025");
    }
    catch (const std::exception& e)
    {
        // the connect is successful
        std::cout << "err:" << e.what() << std::endl;
    }

    //netlog.printf("connecting remote tcp://192.168.191.2:1025");
   // netlog.printf("waiting info (loop)");
    while (true)
    {

        zmq::message_t recvmessage;
        zmq::message_t sendmessage;

        // this is protobuf .i thought it is good
        Req->set_cmd_code(0);
        Req->set_cmd_dat_len(0);
        Req->set_cmd_type(NetMsg::MsgType::Dat);

        sendmessage.rebuild(Req->ByteSizeLong());
        Req->SerializeToArray(sendmessage.data(), sendmessage.size());

        Reqer.send(sendmessage, zmq::send_flags::none);// it print "Resource temporarily unavailable"!!!!!!!!!!!!!!!!

        Reqer.recv(recvmessage, zmq::recv_flags::none);

        Cor->ParseFromArray(recvmessage.data(), recvmessage.size());

        Settings::GetInstance()->SetRobotAtt(Robot1, Cor->ix(), Cor->iy(), Cor->iyaw());

        Sleep(1);

    }
}

resp


// it works on a non-blocking thread 
void NetDispatch()
{
    auto pReqHeader
        = std::make_shared<NetMsg::ReqHeader>();

    auto pCorInfo = std::make_shared<NetMsg::PubSub_Coordinate>();
    std::cout << "bind 1025\r\n" ;
    Resp.bind("tcp://*:1025");
        std::cout << std::get<0>(zmq::version()) << std::endl;
    std::cout << std::get<1>(zmq::version()) << std::endl;
    std::cout << std::get<2>(zmq::version()) << std::endl;
    while(true)
    {
        zmq::message_t recvmsg;

        std::cout << "waiting \r\n" ;
        Resp.recv(&recvmsg);
        printf("%s\r\n",zmq_strerror(zmq_errno()));// it print "Resource temporarily unavailable"!!!!!!!!!!!!!!!!
        std::cout << "recv \r\n" ;
        pReqHeader->ParseFromArray(recvmsg.data(),recvmsg.size());
        //pReqHeader->PrintDebugString();

        pCorInfo->set_ix(g_Pose.iX);
        pCorInfo->set_iy(g_Pose.iY);
        pCorInfo->set_iyaw(g_Pose.iYaw/10.f);

        //pCorInfo->PrintDebugString();
        zmq::message_t message(pCorInfo->ByteSizeLong());
        pCorInfo->SerializeToArray(message.data(),pCorInfo->ByteSizeLong());
        pCorInfo->PrintDebugString();
        Resp.send(message);

        usleep(20000);
    }

}

%%

i thought i does not require it work on non-block. so i can't understand this problem . maybe this is bug!

stkw0 commented 1 year ago

I had the same problem with version 4.9.0. From the source code it seems that in case of error it throws an exception and if everything works fine it returns the number of read bytes. So, my understanding is that we should not check for the errno but handle the exception if they are thrown. What I don't understand is why it's marked with NODISCARD, it feels like the returned number of bytes can be safely ignored.

It would be nice if those details were better documented.

btw here are the relevant code:

    ZMQ_NODISCARD
    recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
    {
        const int nbytes =
          zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
        if (nbytes >= 0) {
            assert(msg.size() == static_cast<size_t>(nbytes));
            return static_cast<size_t>(nbytes);
        }
        if (zmq_errno() == EAGAIN)
            return {};
        throw error_t();
gummif commented 1 year ago

If there is no error then I think it will not set errno. But you don't need to check errno at all because either the function is successful (non-null result), or null result (only if non-blocking) or throws an exception.

stkw0 commented 1 year ago

True, so I guess there is really a bug in some place. I received the same error ("Resource temporarily unavailable") but no exception was thrown and the message was in fact successfully received.