【发布时间】:2021-09-30 14:30:30
【问题描述】:
我想在一个方法中建立一个套接字连接,并在一个类的另一个方法中使用这个连接。在第一种方法(我建立连接)中,我可以根据需要从套接字读取和写入,但在第二种方法中,我总是收到Bad file descriptor 错误。 请注意,我使用的是 Boost 1.65.1 版本。
我创建了一个可重现的小示例(我添加了一些日志以进行澄清):
代码.h
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class SocketManager {
tcp::socket *sock;
boost::asio::io_service *io_service;
tcp::acceptor *acceptor;
public:
virtual void initialize(); // works
virtual void evaluate(); // fails
};
code.cc
#include "code.h"
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
int main() {
SocketManager sm;
sm.initialize();
sm.evaluate();
return 0;
}
void SocketManager::initialize() {
boost::asio::io_service _io_service;
io_service = &_io_service;
tcp::acceptor a(*io_service, tcp::endpoint(tcp::v4(), 1337));
acceptor = &a;
tcp::socket sock_(*io_service);
sock = &sock_;
a.accept(*sock);
char data[1024];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error)
throw boost::system::system_error(error); // No Error here!
boost::asio::write(*sock, boost::asio::buffer(data, length));
cout << io_service->stopped() << endl; // prints 0
cout << acceptor->is_open() << endl; // prints 1
cout << sock->is_open() << endl; // prints 1
}
void SocketManager::evaluate() {
cout << io_service->stopped() << endl; // prints 0
cout << acceptor->is_open() << endl; // prints 1
cout << sock->is_open() << endl; // prints 1
char data[1024];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error)
throw boost::system::system_error(error); // Error: "Bad file descriptor"
}
上面代码在客户端使用时的输出:
root@5531547d4baf:/cpp# ./a.out
0
1
1
0
1
1
terminate called after throwing an instance of 'boost::system::system_error'
what(): Bad file descriptor
Aborted
请注意,在两种方法中引发错误的代码是完全相同的代码(在第一种方法中它可以正常工作,而在第二种方法中它会引发Bad file descriptor 错误)。
我怀疑切换到新功能时io_service不再有效,所以我已经尝试了关联的poll和run功能,但没有成功。
我还尝试将boost::asio::buffer 替换为boost::asio::mutable_buffer 和boost::asio::mutable_buffer。但是,完全相同的代码在第一种方法中工作,所以我怀疑函数调用没问题!
【问题讨论】:
-
不确定我是否完全理解问题,但
SocketManager的sock、io_service和acceptor成员被初始化为指向SocketManager::initialize中的局部变量。完成后,您将拥有悬空指针。 -
@G.M.这大概就是问题所在。我可以以某种方式将它们移动到实例范围吗? (我无法使用构造函数初始化它们)
-
抱歉,刚刚看到
"I cannot initialize them using a constructor"评论。我能问为什么不吗? -
当我阅读您的回答时,我意识到我可以使用构造函数。请再次显示您的答案,以便我接受!非常感谢!
标签: c++ sockets boost boost-asio