来自 boost 的 Udp 服务器不能在多线程上工作,但只能在主线程上工作
Udp server from boost not working on multithreading, but work only on the main thread
我有一个异步 udp 服务器 boost::asio
但问题是:
如果我在线程上启动它,服务器将无法工作
但是如果我在主线程上启动它(阻塞服务)它正在工作...
我试过用叉子来做,但 eiser 不行
class Server {
private:
boost::asio::io_service _IO_service;
boost::shared_ptr<boost::asio::ip::udp::socket> _My_socket;
boost::asio::ip::udp::endpoint _His_endpoint;
boost::array<char, 1000> _My_Buffer;
private:
void Handle_send(const boost::system::error_code& error, size_t size, std::string msg) {
//do stuff
};
void start_send(std::string msg) {
_My_socket->async_send_to(boost::asio::buffer(msg), _His_endpoint,
boost::bind(&Server::Handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred, msg));
};
void Handle_receive(const boost::system::error_code& error, size_t size) {
//do stuff
};
void start_receive(void) {
_My_socket->async_receive_from(
boost::asio::buffer(_My_Buffer), _His_endpoint,
boost::bind(&Server::Handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
public:
Server(int port):
_IO_service(),
_My_socket(boost::make_shared<boost::asio::ip::udp::socket>(_IO_service, \
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port)))
{
start_receive();
};
void Launch() {
_IO_service.run();
};
};
objective是后台调用Server::Launch
首先你在 start_send
.
中有未定义的行为
async_send_to
returns 立即,所以 msg
作为局部变量在 start_send
returns 时被销毁。当您调用 async_send_to
时,您必须确保 msg
在异步操作完成之前未被销毁。描述的内容 in documentation -
Although the buffers object may be copied as necessary, ownership of
the underlying memory blocks is retained by the caller, which must
guarantee that they remain valid until the handler is called.
可以通过多种方式解决,最简单的就是使用string作为数据成员(作为发送数据的缓冲区):
class Server {
//..
std::string _M_toSendBuffer;
//
void start_send(std::string msg) {
_M_toSend = msg; // store msg into buffer for sending
_My_socket->async_send_to(boost::asio::buffer(_M_toSend), _His_endpoint,
boost::bind(&Server::Handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
_M_toSend));
};
另一种解决方案是将msg
包装成智能指针以延长其生命周期:
void Handle_send(const boost::system::error_code& error, size_t size,
boost::shared_ptr<std::string> msg) {
//do stuff
};
void start_send(std::string msg) {
boost::shared_ptr<std::string> msg2 = boost::make_shared<std::string>(msg); // [1]
_My_socket->async_send_to(boost::asio::buffer(*msg2), _His_endpoint,
boost::bind(&Server::Handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
msg2)); // [2]
};
在 [1] 行中我们创建 shared_ptr
获取 msg
内容,然后在 [2] 行中 shared_ptr
的引用计数器在调用 bind
时增加, 因此字符串的生命周期被延长,并在处理程序被调用后被销毁。
关于您的 not-working 基于线程的版本。您没有显示调用 Launch
的代码,但也许您只是不加入此线程?
Server s(3456);
boost::thread th(&Server::Launch,&s);
th.join(); // are you calling this line?
或者您的代码在 start_send
.
中无法通过 UB 运行
我有一个异步 udp 服务器 boost::asio 但问题是: 如果我在线程上启动它,服务器将无法工作 但是如果我在主线程上启动它(阻塞服务)它正在工作...
我试过用叉子来做,但 eiser 不行
class Server {
private:
boost::asio::io_service _IO_service;
boost::shared_ptr<boost::asio::ip::udp::socket> _My_socket;
boost::asio::ip::udp::endpoint _His_endpoint;
boost::array<char, 1000> _My_Buffer;
private:
void Handle_send(const boost::system::error_code& error, size_t size, std::string msg) {
//do stuff
};
void start_send(std::string msg) {
_My_socket->async_send_to(boost::asio::buffer(msg), _His_endpoint,
boost::bind(&Server::Handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred, msg));
};
void Handle_receive(const boost::system::error_code& error, size_t size) {
//do stuff
};
void start_receive(void) {
_My_socket->async_receive_from(
boost::asio::buffer(_My_Buffer), _His_endpoint,
boost::bind(&Server::Handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
public:
Server(int port):
_IO_service(),
_My_socket(boost::make_shared<boost::asio::ip::udp::socket>(_IO_service, \
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port)))
{
start_receive();
};
void Launch() {
_IO_service.run();
};
};
objective是后台调用Server::Launch
首先你在 start_send
.
async_send_to
returns 立即,所以 msg
作为局部变量在 start_send
returns 时被销毁。当您调用 async_send_to
时,您必须确保 msg
在异步操作完成之前未被销毁。描述的内容 in documentation -
Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.
可以通过多种方式解决,最简单的就是使用string作为数据成员(作为发送数据的缓冲区):
class Server {
//..
std::string _M_toSendBuffer;
//
void start_send(std::string msg) {
_M_toSend = msg; // store msg into buffer for sending
_My_socket->async_send_to(boost::asio::buffer(_M_toSend), _His_endpoint,
boost::bind(&Server::Handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
_M_toSend));
};
另一种解决方案是将msg
包装成智能指针以延长其生命周期:
void Handle_send(const boost::system::error_code& error, size_t size,
boost::shared_ptr<std::string> msg) {
//do stuff
};
void start_send(std::string msg) {
boost::shared_ptr<std::string> msg2 = boost::make_shared<std::string>(msg); // [1]
_My_socket->async_send_to(boost::asio::buffer(*msg2), _His_endpoint,
boost::bind(&Server::Handle_send, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
msg2)); // [2]
};
在 [1] 行中我们创建 shared_ptr
获取 msg
内容,然后在 [2] 行中 shared_ptr
的引用计数器在调用 bind
时增加, 因此字符串的生命周期被延长,并在处理程序被调用后被销毁。
关于您的 not-working 基于线程的版本。您没有显示调用 Launch
的代码,但也许您只是不加入此线程?
Server s(3456);
boost::thread th(&Server::Launch,&s);
th.join(); // are you calling this line?
或者您的代码在 start_send
.