如何在回调之外操作 libevent bufferevents

问题描述 投票:0回答:1

我使用 libevent 编写客户端-服务器应用程序,在客户端我想连续等待来自控制台的输入。我尝试在线程中运行

event_base_dispatch
,并在主线程中,我要求输入字符串并将其添加到 bufferevent。

    std::thread libevthr(libev_start, base);    

    std::string s;
    do
    {
        cin >> s;
        bufferevent_write(bev, "Hello, world!", 13); 

    } while(s != "xxx");
    
    libevthr.join();      

由于某种原因,这不起作用,但如果我将

bufferevent_write
放入其中一个回调中,它就可以正常工作

void event_cb(struct bufferevent *bev, short events, void *ptr)
{
    if (events & BEV_EVENT_CONNECTED) {
         /* We're connected to 127.0.0.1   Ordinarily we'd do
            something here, like start reading or writing. */
        bufferevent_write(bev, "Hello, world!", 13);
        std::cout << "Connected" << std::endl;
    }
    
    if (events & BEV_EVENT_ERROR) {  
        if (EVUTIL_SOCKET_ERROR() == 10054) 
            cout << "Server stopped working!" << endl;
        else 
            cout  << "Error has happened" << endl;
    }

    if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR))
    {
        bufferevent_free(bev);   
    }     
}

你能解释一下我应该如何正确地写这个吗?

完整代码在这里:

#include "UClient.h"
#include <iostream>
#include "event2/event.h"
#include "event2/listener.h"
#include "event2/bufferevent.h"
#include "event2/buffer.h"

#include <thread>

using std::cout, std::cin, std::endl;

void event_cb(struct bufferevent *bev, short events, void *ptr)
{
    if (events & BEV_EVENT_CONNECTED) {
         /* We're connected to 127.0.0.1   Ordinarily we'd do
            something here, like start reading or writing. */
        bufferevent_write(bev, "Hello, world!", 13);
        std::cout << "Connected" << std::endl;
    }
    
    if (events & BEV_EVENT_ERROR) {  
        if (EVUTIL_SOCKET_ERROR() == 10054) 
            cout << "Server stopped working!" << endl;
        else 
            cout  << "Error has happened" << endl;
    }

    if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR))
    {
        bufferevent_free(bev);     
    } 

}

void write_cb(struct bufferevent *bev, void *ctx)
{
    cout << 'Data was written' << endl;
}



void libev_start(event_base *base)
{
    event_base_dispatch(base);    
}

int main()
{
    int port = 9554;
    
    struct event_base *base;         
    struct bufferevent *bev;        
    struct sockaddr_in cl_inf;         

    if (!initWinsock()) {
        perror("Failed to initialize Winsock");
        return 1;        
    }

    base = event_base_new();

    ZeroMemory(&cl_inf, sizeof(cl_inf));
    in_addr serv_ip;

    inet_pton(AF_INET, "127.0.0.1", &serv_ip);

    cl_inf.sin_family = AF_INET;
    cl_inf.sin_addr = serv_ip;
    cl_inf.sin_port = htons(port);

    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);

    bufferevent_setcb(bev, NULL, write_cb, event_cb, NULL);  

    if (bufferevent_socket_connect(bev,
        (struct sockaddr *)&cl_inf, sizeof(cl_inf)) < 0) {
        /* Error starting connection */
        std::cout << "Can't connect to server!" << std::endl;
        bufferevent_free(bev);
        return -1;
    }

    bufferevent_enable(bev, EV_READ | EV_WRITE);

    
    std::thread libevthr(libev_start, base);    

    std::string s;
    do
    {
        cin >> s;
    } while(s != "xxx");
    
    libevthr.join();        
    std::cout << "client finished working";
    return 0;

}
c++ libevent
1个回答
0
投票

您需要“告诉”libevent“我们处于多线程上下文中”, 然后 libevent 将在其 API 中执行一些同步操作, 即 bufferevent_write。

为此,请将

evthread_use_windows_threads();
(因为您正在调用某些 Windows API)放在任何其他 libevent 调用之前。

祝你好运:)

© www.soinside.com 2019 - 2024. All rights reserved.