[英]Why does this Boost TCP socket work in one method and not in another?
I want to establish a socket connection in one method and use this connection in another method of a class.我想在一个方法中建立一个套接字连接,并在一个类的另一个方法中使用这个连接。 While in the first method (where I establish the connection) I can read and write from and to the socket as much as I want, in the second method I always get a
Bad file descriptor
error.虽然在第一种方法(我建立连接的地方)中,我可以根据需要从套接字读取和向套接字写入,但在第二种方法中,我总是收到
Bad file descriptor
错误。 Note that I use version 1.65.1
of Boost.请注意,我使用的是
1.65.1
版的 Boost。
I created a small reproducible example (I added some logs for clarification):我创建了一个小的可重现示例(我添加了一些日志以进行澄清):
code.h代码.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代码.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"
}
Output of the code above when used with a client:与客户端一起使用时上述代码的输出:
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
Note that the code that throws the error is the exact same code in both methods (in the first one it works without any error and in the second one it throws a Bad file descriptor
error).请注意,抛出错误的代码在两种方法中是完全相同的代码(在第一个方法中它没有任何错误,而在第二个方法中它抛出一个
Bad file descriptor
错误)。
I suspect that the io_service
is no longer valid when switching to the new function, so I have already experimented with the associated poll
and run
functions without success.我怀疑切换到新函数时
io_service
不再有效,所以我已经尝试了相关的poll
和run
函数,但没有成功。
I also tried to replace the boost::asio::buffer
with a boost::asio::mutable_buffer
and a boost::asio::mutable_buffer
.我也试图取代
boost::asio::buffer
带boost::asio::mutable_buffer
和boost::asio::mutable_buffer
。 However, the exact same code works in the first method, so I suspect that the function calls are alright!但是,完全相同的代码在第一种方法中有效,所以我怀疑函数调用没问题!
As per the comment sock
, io_service
and acceptor
members of SocketManager
are initialized to point to local variables within SocketManager::initialize
.根据注释
sock
, SocketManager
io_service
和acceptor
成员被初始化为指向SocketManager::initialize
局部变量。 When that completes you then have dangling pointers.完成后,您将获得悬空指针。
I don't see any reason to use pointers at all here.我在这里根本看不到任何使用指针的理由。 Just make them non-pointer data members and initialize them in a constructor (untested)...
只需使它们成为非指针数据成员并在构造函数中初始化它们(未经测试)...
class SocketManager {
boost::asio::io_service io_service;
tcp::acceptor acceptor;
tcp::socket sock;
public:
SocketManager ()
: acceptor(io_service, tcp::endpoint(tcp::v4(), 1337))
, sock(io_service)
{}
...
};
Note that the io_service
member is declared first as it must be initialized before sock
and acceptor
.请注意,
io_service
成员首先声明,因为它必须在sock
和acceptor
之前初始化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.