【发布时间】:2014-08-25 14:37:21
【问题描述】:
我一直在尝试使用 boost 实现一个简单的 tcp 服务器,它接受客户端连接,并通过调用服务器公开的方法将一些信息发送回客户端。
这是我根据 Boost 教程创建的课程:
#define WIN32_LEAN_AND_MEAN
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
#include <ctime>
#include <iostream>
#include <string>
#include "Logger.h"
class tcp_server_connection
: public boost::enable_shared_from_this<tcp_server_connection>
{
public:
typedef boost::shared_ptr<tcp_server_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_server_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start(string message)
{
swap(m, message);
boost::asio::async_write(socket_, boost::asio::buffer(m),
boost::bind(&tcp_server_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
private:
tcp_server_connection(boost::asio::io_service& io_service)
: socket_(io_service)
{
Logger::Log("main.log", "New TCP Server Connection");
}
void handle_write(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (error) {
Logger::Log("main.log", "TCP Server Write Error: ");
}
}
tcp::socket socket_;
string m;
};
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service, int port)
: acceptor_(io_service, tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), port))
{
start_accept();
}
void write(string message) {
connection->start(message);
}
private:
void start_accept()
{
connection = tcp_server_connection::create(acceptor_.get_io_service());
acceptor_.async_accept(connection->socket(),
boost::bind(&tcp_server::handle_accept, this, connection,
boost::asio::placeholders::error));
}
void handle_accept(tcp_server_connection::pointer new_connection,
const boost::system::error_code& error)
{
if (!error)
{
Logger::Log("main.log", "TCP Server Accepted Connection");
}
else {
Logger::Log("main.log", "TCP Server Error accepting Connection");
}
}
tcp::acceptor acceptor_;
tcp_server_connection::pointer connection;
};
我通过这个方法启动一个线程来启动服务器:
void SetupServer() {
boost::asio::io_service io_service;
server = new tcp_server(io_service, serverPort);
io_service.run();
}
当我想向客户端写一些东西时,我调用 server->write("Some Text") ,但是 async_write 引发和异常说“访问冲突写入位置”。我相信可能有一些对象在它应该被清理之前被清理了,但我不明白为什么以及在哪里,所以如果有人能给我一些关于为什么会发生这种情况以及如何解决它的见解,我将不胜感激。
提前感谢您的帮助。
【问题讨论】:
-
您从哪里调用
server->write()方法?您的SetupServer方法在本地声明 io_service。一旦超出范围,所有使用该 io_service 的套接字/连接/操作都将是未定义的行为。 -
@DaveS 你是绝对正确的,我只是在几分钟前把我的头撞到墙上几次后才发现:) 为了解决这个问题,我使用 new 显式创建了 io_service 变量,以便范围更改时未释放内存,并且一切正常。我将发布我找到的解决方案作为答案,希望它可以在将来对某人有所帮助。
标签: c++ multithreading boost boost-asio boost-thread