ZMQ_DONTWAIT标志不起作用?

时间:2013-03-23 01:01:00

标签: c++ block zeromq

我在我的应用程序中使用ZeroMQ进行联网,手册指出通过向ZMQ_DONTWAITflags中的send参数提供recv标记会导致函数不阻止线程。但它在我的情况下不起作用:

            std::cout << "a";
            if(ToSend.try_pop(send))
            {
                std::cout << "b";
                local.send(send.data(),send.size(),ZMQ_DONTWAIT);
            }
            std::cout << "c";
            if(local.recv(recv.data(),Networking::max_packet,ZMQ_DONTWAIT))
                std::cout << "Received: " << (char*)recv.data() << std::endl;
            std::cout << "d" << std::endl;

打印:

abcdab

我做了一个小课,让事情变得更轻松:

客户端类(为简化而从所有“未使用”的东西中划分出来)

class client
{
public:
    client()
    {

    }
    inline bool init(unsigned short threads = 1)
    {
        Running = true;
        context = zmq_init (threads);
        if(context == NULL)
            return false;
        socket = zmq_socket (context, ZMQ_REQ);
        if(socket == NULL)
            return false;
        return true;
    }
    inline int connect(const char * address, unsigned short port)
    {
        return zmq_connect(socket,string_format("tcp://%s:%d",address,port).c_str());
    }
    inline bool send (void *data, size_t len_, int flags_ = 0)
    {
        message_t request (len_);
        memcpy ((void *) request.data (), data, len_);
        int rc = zmq_send (socket, request.data(), request.size(), flags_);
        if (rc >= 0)
            return true;
        if (rc == -1 && zmq_errno () == EAGAIN)
            return false;
        throw error_t ();
    }
    inline bool recv (void * data, size_t len_, int flags_)
    {
        message_t reply(len_);
        int rc = zmq_recv (socket, reply.data(), len_, flags_);
        if (rc >= 0)
        {
            memcpy (data,(void *)reply.data(), reply.size());
            return true;
        }
        if (rc == -1 && zmq_errno () == EAGAIN)return false;
        throw error_t ();
    }
    inline bool IsRunning()
    {
        return Running;
    }
private:
    void * context;
    void * socket;
    std::atomic<bool> Running;
};

这是工作线程:

namespace Data
{
    Concurrency::concurrent_queue <message_t> ToSend;
    void Processor(char * address, unsigned short port, unsigned short threads)
    {
        client local;
        if(!local.init(threads))return;
        if(local.connect(address,port) != 0)return;
        message_t recv(Networking::max_packet);
        message_t send(Networking::max_packet);
        while(local.IsRunning())
        {
            std::cout << "a";
            if(ToSend.try_pop(send))
            {
                std::cout << "b";
                local.send(send.data(),send.size(),ZMQ_DONTWAIT);
            }
            std::cout << "c";
            if(local.recv(recv.data(),Networking::max_packet,ZMQ_DONTWAIT))
                std::cout << "Received: " << (char*)recv.data() << std::endl;
            std::cout << "d" << std::endl;
        }
    }
};

这里存在问题。我只是不知道为什么它不起作用。

这是我启动工作线程的方式:

int Thread(char * address, unsigned short port, unsigned short threads)
{
    std::thread data(Data::Processor,address,port,threads);
    data.detach();
    while(!Data::status){}
    return Data::status;
}
int main(int argc, char* argv[])
{

    std::thread s(Server::RUN);

    Client::message_t tosend(14);
    memcpy((void*)tosend.data(),"Hello World !\0",14);

    Client::Data::ToSend.push(tosend);

    std::cout << Client::Thread("127.0.0.1",5555,1) << std::endl;

    s.join();
    return 0;
}

这一切似乎都是正确的,为什么recv / send会阻塞我的线程?为什么国旗不起作用?

1 个答案:

答案 0 :(得分:1)

打印“abcd”然后打印“ab”。这意味着代码

std::cout << "a";
if(ToSend.try_pop(send))
{
    std::cout << "b";

执行了两次虽然你在问题末尾显示的代码暗示你只做了一次ToSend.push()。

您是否附加了调试器以查看挂起的线程以及它的callstack是什么?

  • 将std :: cout放在互斥/批处理后面,这样你就知道一次只有一个线程在写,并报告你是哪个线程。
  • 将每个输出放在它自己的行上,这样就不会因为缓冲而丢失一个字母。
  • 如果您不阻止数据,您希望如何接收数据?你在某处有select / poll / WaitForSingleObject调用吗?