gpt4 book ai didi

c++ - libev 将套接字设置为无超时阻塞

转载 作者:行者123 更新时间:2023-11-28 00:51:42 31 4
gpt4 key购买 nike

Rant:我真的不喜欢 boost::asio,所以我一直在寻找替代方案并遇到了 libev。这对我来说似乎很简单,但正在做一些我无法理解的事情。如果一个线程中的问题太多,请告诉我。

1) 我将监听套接字设置为 NON_BLOCK,我还将每个接受的传入连接设置为 NON_BLOCK,但在代码中某处套接字变成了 BLOCK。例如:

bool Server::Start()
{
// Setup event loop
loop = ev_default_loop(EVBACKEND_SELECT); //EVFLAG_AUTO ?
// Create Socket
sockfd = socket(PF_INET, SOCK_STREAM, 0);
addr_len = sizeof(addr)
// Set Socket to non blocking
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
if (fcntl(sockfd, F_GETFL) & O_NONBLOCK) std::cout << "Socket is NONBLOCK" << std::endl;
else std::cout << "Socket is BLOCK" << std::endl;
if (sockfd < 0) {
std::cout << "ERROR opening socket" << std::endl;
return false;
}
bzero((char *)&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
// Bind port to socket
if (bind(sockfd,(struct sockaddr*)&addr, sizeof(addr))!=0) {
std::cout << "bind error" << std::endl;
return false;
}
// Listen
if (listen(sockfd, 2) < 0) {
std::cout << "listen error" << std::endl;
return false;
}
// Initialize and start a watcher to accepts client requests
ev_io_init(&w_accept, accept_cb, sockfd, EV_READ);
ev_io_start(loop, &w_accept);
return true;
}

我试图让主循环也不会阻塞:

void Server::MainLoop()
{
// Start infinite loop
while (1) {
ev_loop(loop, EVLOOP_NONBLOCK);
}
}

但好像并没有什么不同。请不要将我重定向到我已阅读的文档(互联网上唯一可用的文档来源)。

我为已接受的客户端套接字执行此操作:

void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
....
c->client_sd = accept(watcher->fd, (struct sockaddr *)&c->client_addr, &c->client_len);
....
ev_io *w_client = (struct ev_io*) malloc (sizeof(struct ev_io));
ev_io_init(w_client, read_cb, c->client_sd, EV_READ);
ev_io_start(loop, w_client);
fcntl(watcher->fd, F_SETFL, fcntl(watcher->fd, F_GETFL) | O_NONBLOCK);

然而每次执行我的读取回调时,套接字都神奇地设置为 BLOCK

2) 我尝试为套接字设置超时:结构时间超时;

timeout.tv_sec = 10;
timeout.tv_usec = 0;

if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof(timeout)) < 0)
error("setsockopt failed\n");

if (setsockopt (sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
sizeof(timeout)) < 0)
error("setsockopt failed\n");

(取自此处:this question)它根本行不通。这是因为套接字重置为 BLOCKing 模式吗?

3) 我看到了 libev 的 C++ 包装器。我非常讨厌我必须让回调函数成为静态函数,它毁了我的一切。然而,我看到的所有示例都使用:

signal.loop.break_loop();

loop.run(0);

有趣的是,它产生了:

error: ‘struct ev::loop_ref’ has no member named ‘break_loop’ error: ‘struct ev::default_loop’ has no member named ‘run’

关于 Debian Squeeze。

所以,我要问的是:

  1. 什么,谁,套接字在哪里从 NON_BLOCK 更改为 BLOCK?
  2. 如何(如果)为套接字设置超时(阻塞或非阻塞)
  3. ev++.h 有什么问题,为什么那些好人使用我不能使用的包装器?

请记住,我可以使用套接字读取和发送数据,但以阻塞方式,没有超时。此外,由于这是一个服务器,我需要将代码保存在类中,因为我必须为每个连接的客户端保存消息。制作这种静态或非类方法只会毁了它,或者迫使我采取一种非常不同的方法。

PS:有没有 libev 的替代品?

最佳答案

您没有将客户端 FD 设置为非阻塞模式。您正在设置监听套接字 FD。

关于c++ - libev 将套接字设置为无超时阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13783199/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com