Boost::asio async_read_some工作一次,然后停止工作,为什么?(要查看使用)
boost::asio async_read_some works once then stops working, why? (uses shared_ptr)
我一直在尝试从http://think-async.com/asio/boost_asio_1_3_0/doc/html/boost_asio/example/http/server/connection.cpp开始并修改它以满足我的需求。我想一个接一个地接受多个客户端,并最终通过TCP读取数据。我的服务器工作正常,如果我运行它,然后在另一个shell中使用
nc localhost 3731
然后按control-C。第一个客户机已正确断开连接。然后再次输入相同的命令。麻烦来了下一个客户;它接受并打印出读取好的开始,但是当我在第二个客户端上点击control-C时,它似乎没有得到断开连接的消息。我不知道为什么。boost::asio async_read_some有什么帮助吗?
下面是输出调试消息,显示第一个客户端工作,然后后续客户端没有正确断开连接:
./a.out
Made connection at address 80x2240370
Added connection to ConnectionManager at 80x2240370
Starting read at address 80x2240370
Made connection at address 80x22449f0
Did read of 0 with error code asio.misc:2
Accepting bytes.
Removing connection to ConnectionManager at 80x2240370
Destroying connection at address 80x2240370
Added connection to ConnectionManager at 80x22449f0
Starting read at address 80x22449f0
Made connection at address 80x2248af0
下面是完整的源代码,为了简洁而编辑,但仍然显示了问题:
// compile with: g++ asiohelp.cpp -lboost_system -lpthread -std=c++11
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/array.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <set>
#include <vector>
#include <string>
#define CONTROL_PORT "3731"
#define CONTROL_BIND_ADDRESS "127.0.0.1"
namespace hsd {
namespace net {
class HSDConnectionManager;
class HSDConnection: public boost::enable_shared_from_this<HSDConnection> {
boost::asio::ip::tcp::socket socket_;
boost::array<char, 16384> readBuffer_;
HSDConnectionManager& connectionManager_;
public:
explicit HSDConnection(boost::asio::io_service& io_service,
HSDConnectionManager& manager);
~HSDConnection(void);
boost::asio::ip::tcp::socket& socket(void);
/// Start the first asynchronous operation for the connection.
void startRead(void);
void handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred);
void stop(void);
private:
void continueRead(void);
};
typedef boost::shared_ptr<HSDConnection> ConnectionPtr;
}
}
namespace hsd {
namespace net {
class HSDConnectionManager: private boost::noncopyable {
public:
void start(ConnectionPtr c);
void stop(ConnectionPtr c);
void stop_all();
private:
std::set<ConnectionPtr> connections_;
};
}
}
namespace hsd {
namespace net {
class ControlServer {
public:
// Construct the server to listen on the specified TCP address and port
explicit ControlServer(boost::asio::io_service& io_service_,
const std::string& address, const std::string& port);
virtual ~ControlServer(void);
// Run the server's io_service loop.
void run();
// Stop the server.
void stop();
// Handle packet
virtual void packetReceived(std::string result);
private:
/// Handle completion of an asynchronous accept operation.
void handleAccept(const boost::system::error_code& e);
/// Handle a request to stop the server.
void handleStop();
/// The io_service used to perform asynchronous operations.
boost::asio::io_service io_service_;
/// Acceptor used to listen for incoming connections.
boost::asio::ip::tcp::acceptor acceptor_;
/// The connection manager which owns all live connections.
HSDConnectionManager connectionManager_;
/// The next connection to be accepted.
ConnectionPtr nextConnection_;
};
}
}
using namespace std;
using namespace boost::system::errc;
namespace hsd {
namespace net {
ControlServer::ControlServer(boost::asio::io_service& io_service_,
const std::string& address, const std::string& port) :
io_service_(), acceptor_(io_service_), connectionManager_(), nextConnection_() {
nextConnection_ = ConnectionPtr(
new HSDConnection(io_service_, connectionManager_));
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(address, port);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor_.open(endpoint.protocol());
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor_.bind(endpoint);
acceptor_.listen();
acceptor_.async_accept(nextConnection_->socket(),
boost::bind(&ControlServer::handleAccept, this,
boost::asio::placeholders::error));
}
ControlServer::~ControlServer(void) {
cout << "Destroying ControlServern";
}
void ControlServer::handleAccept(const boost::system::error_code& e) {
if (e == success) {
connectionManager_.start(nextConnection_);
nextConnection_.reset(
new HSDConnection(io_service_, connectionManager_));
//nextConnection_ = ConnectionPtr(new HSDConnection(io_service_,
// connectionManager_, *hsPacketReaderListener_s));
acceptor_.async_accept(nextConnection_->socket(),
boost::bind(&ControlServer::handleAccept, this,
boost::asio::placeholders::error));
}
}
void ControlServer::packetReceived(std::string result) {
cout << "Got packet: " << result << "n";
}
}
}
using namespace std;
namespace hsd {
namespace net {
boost::asio::ip::tcp::socket& HSDConnection::socket(void) {
return socket_;
}
HSDConnection::HSDConnection(boost::asio::io_service& io_service,
HSDConnectionManager& manager) :
socket_(io_service), connectionManager_(manager), readBuffer_()
{
cout << "Made connection at address " << ios::hex << this << "n";
}
HSDConnection::~HSDConnection(void) {
cout << "Destroying connection at address " << ios::hex << this << "n";
}
void HSDConnection::handleRead(const boost::system::error_code& e,
std::size_t bytesTransferred) {
cout << "Did read of " << bytesTransferred << " with error code " << e
<< "n";
std::string byteString(readBuffer_.data(), bytesTransferred);
vector<string> result;
cout << "Accepting bytes.n";
//hsPacketCore_.acceptBytes(byteString, result);
for (string &packet : result) {
//listener_->packetReceived(packet);
}
if (e == boost::system::errc::success
|| e == boost::asio::error::operation_aborted) {
continueRead();
} else if (bytesTransferred == 0) {
connectionManager_.stop(shared_from_this());
}
}
void HSDConnection::continueRead(void) {
cout << "Continuing read at address " << ios::hex << this << "n";
socket_.async_read_some(boost::asio::buffer(readBuffer_),
boost::bind(&HSDConnection::handleRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void HSDConnection::startRead(void) {
cout << " Starting read at address " << ios::hex << this << "n";
socket_.async_read_some(boost::asio::buffer(readBuffer_),
boost::bind(&HSDConnection::handleRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void HSDConnection::stop(void) {
socket_.close();
}
}
}
namespace hsd {
namespace net {
void HSDConnectionManager::start(ConnectionPtr c) {
connections_.insert(c);
std::cout << "Added connection to ConnectionManager at " << std::ios::hex << c
<< "n";
c->startRead();
}
void HSDConnectionManager::stop(ConnectionPtr c) {
std::cout << "Removing connection to ConnectionManager at " << std::ios::hex
<< c << "n";
connections_.erase(c);
c->stop();
}
}
}
using boost::asio::ip::tcp;
using namespace std;
using namespace hsd::net;
int main()
{
try
{
// We need to create a server object to accept incoming client connections.
boost::asio::io_service io_service;
// The io_service object provides I/O services, such as sockets,
// that the server object will use.
ControlServer server(io_service, CONTROL_BIND_ADDRESS, CONTROL_PORT);
// Run the io_service object to perform asynchronous operations.
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
您有两个io_service实例。行为上的区别在于,您在从两个不同的io_service实例初始化的套接字上调用async_accept。这种混淆来自于将参数io_service_命名为与成员变量相同的方式。我设法通过使成员变量为引用来修复您的代码。
<>之前///执行异步操作的io_service。boost:: asio: io_service& io_service_;之前,然后在构造函数的形式形参中消除变量的歧义,并用该形参初始化成员变量。
<>之前ControlServer:: ControlServer (boost:: asio: io_service& io_service,Const std::string& address, Const std::string& port):io_service_ (io_service) acceptor_ (io_service),connectionManager_(), nextConnection_() {之前另一个选项是公开io_service成员变量,然后运行该io_service。
<>之前//io_service对象提供I/O服务,例如socket;//服务器对象将使用的。ControlServer server(CONTROL_BIND_ADDRESS, CONTROL_PORT);//运行io_service对象执行异步操作。.run server.io_service () ();之前我希望这是有意义的,我上周才第一次使用boost::asio,写了一个类似的东西
相关文章:
- Visual Studio 2017 停止工作,并在打开后显示许多控制台窗口
- 自 Windows 10 20H1 以来,具有单独线程的多个窗口停止工作
- C++代码停止工作错误使用cout内部函数
- LoadImage 在 Windows 更新后停止工作
- C++程序工作,但 Windows 显示"程序.exe已停止工作"
- VS 代码 C/C++ 智能感知在更新后停止工作
- 不使用与左右停止工作命名空间 std 的简单比较
- 为什么通过定义另一个指针单元格,整个代码停止工作?
- 德拉吉诺 LG01-S 收到异常数据包并停止工作
- 为什么我的程序在输入main()之前停止工作
- 为什么这是为了使程序停止工作?(C )
- boost::asio http客户端停止工作,我不知道为什么
- 为什么Qt中的拖放停止工作
- 为什么我的低级窗口钥匙钩停止工作
- 为什么这段代码会导致程序停止工作
- 为什么我的复制列表初始化停止工作后,我添加继承
- 为什么这段代码会导致我的程序停止工作
- Boost::asio async_read_some工作一次,然后停止工作,为什么?(要查看使用)
- 使用FindWindowEx的程序在Server 2003上停止工作,为什么
- 为什么我的程序停止工作了?我的指示是错的吗?