RaG*_*__M 5 c++ boost tcp blocking boost-asio
为了测试我的服务器,我从客户端使用 for 循环创建了 100 个请求,当我的服务器正在为第 N 个请求写入响应时,我故意从客户端按了 control+c,就是这样。尽管我尝试使用新连接来连接服务器,但服务器停止并且没有响应,任何人都可以建议我如何使我的服务器稳定并免受此类中断的影响。这是我的服务器:
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 2020))
{
start_accept();
}
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
boost::asio::placeholders::error));
}
void handle_user_read(const boost::system::error_code& err,
std::size_t bytes_transferred)
{
}
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code& error)
{
if (!error)
{
new_connection->start();
start_accept();
}
}
tcp::acceptor acceptor_;
};
Run Code Online (Sandbox Code Playgroud)
这是我的 TCP 连接:
class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
// Start reading messages from the server
start_read();
}
public:
tcp_connection(boost::asio::io_service& io_service) : socket_(io_service),timer_(io_service), io(io_service),timer2_(io_service)
{
}
// Reading messages from the server
void start_read()
{
boost::asio::async_read(socket_, input_buffer_,
boost::asio::transfer_at_least(1),
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error));
timer_.expires_from_now(boost::posix_time::seconds(120));
timer_.async_wait(boost::bind(&tcp_connection::close, shared_from_this()));
}
void close()
{
cout<<"I didn't hear the client yet:closing the socket......"<<endl;
socket_.close();
}
// When stream is received, handle the message from the client
int handle_read(const boost::system::error_code& ec)
{
if (!ec)
{
std::istream is(&input_buffer_);
std::string line;
std::getline(is, line);
messageFromClient_+=line;
messageFromClient_.erase(std::remove(messageFromClient_.begin(), messageFromClient_.end(), '\n'), messageFromClient_.end());
std::size_t found = messageFromClient_.find('\0');
if(found==std::string::npos)
{
boost::asio::async_read(socket_, input_buffer_,
boost::asio::transfer_at_least(1),
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error));
}
else{
performmaj();--my logic never mind.
std::cout << "Request: "<<i<<" is on process......"<<"\n";--mylogic
boost::asio::ip::tcp::no_delay option(true);
socket_.set_option(option);
write();
messageToClient_="";--my logic.
boost::system::error_code tc;
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send, tc);
}
std::cout << "Request: "<<i<<" completed"<<"\n";
++i;
(boost::asio::io_service io);
}else
{
std::cout << "Error on receive: " << ec.message() << "\n";
}
}
void write()
{
try{
boost::asio::write(socket_,boost::asio::buffer(messageToClient_), boost::asio::transfer_at_least(messageToClient_.size()));
}catch(exception e)
{
cout<<e.what()<<endl;
socket_.close();
io.run();
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅下面的代码,其中我使用了 async_write;请注意,我打算写入的字符串大小为:11279204。但在下面的代码中使用 async_write 让我的客户收到更多部分但不完整的meaasage。
class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
// Start reading messages from the server
start_read();
}
public:
tcp_connection(boost::asio::io_service& io_service) : socket_(io_service),timer_(io_service), io(io_service),timer2_(io_service)
{
//io=io_service;
}
// Reading messages from the server
void start_read()
{
boost::asio::async_read(socket_, input_buffer_,
boost::asio::transfer_at_least(1),
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error));
timer_.expires_from_now(boost::posix_time::seconds(120));
timer_.async_wait(boost::bind(&tcp_connection::close, shared_from_this()));
}
void close()
{
cout<<"I didn't hear the client yet:closing the socket......"<<endl;
socket_.close();
}
// When stream is received, handle the message from the client
int handle_read(const boost::system::error_code& ec)
{
if (!ec)
{
std::istream is(&input_buffer_);
std::string line;
std::getline(is, line);
messageFromClient_+=line;
messageFromClient_.erase(std::remove(messageFromClient_.begin(), messageFromClient_.end(), '\n'), messageFromClient_.end());
std::size_t found = messageFromClient_.find('\0');
if(found==std::string::npos)
{
boost::asio::async_read(socket_, input_buffer_,
boost::asio::transfer_at_least(1),
boost::bind(&tcp_connection::handle_read, shared_from_this(),
boost::asio::placeholders::error));
}
else{
performmaj();
cout<<messageToClient_.size()<<endl;--11279204
try{
boost::asio::async_write(socket_, boost::asio::buffer(messageToClient_.data(),messageToClient_.size()),
// boost::asio::transfer_at_least(messageToClient_.size()),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}catch(exception e)
{
Shutdown();
}
}
std::cout << "Request: "<<i<<" completed"<<"\n";
++i;
return 0;
}else
{
std::cout << "Error on receive: " << ec.message() << "\n";
}
}
void Shutdown()
{
try {
socket_.shutdown(socket_.shutdown_both);
socket_.close();
} catch (std::exception &e)
{
std::cout << "Error Closing Socket" << e.what() << std::endl;
}
}
void performmaj()
{
std::size_t found = messageFromClient_.find('\0');
if (found!=std::string::npos)
{
std::cout << "Request: "<<i<<" Recieved"<<"\n";
std::cout << "Request: "<<i<<" is on process......"<<"\n";
if (messageFromClient_.size () > 0) messageFromClient_.resize (messageFromClient_.size () - 1);
messageToClient_=test(messageFromClient_);
messageFromClient_="";
messageToClient_.erase(std::remove(messageToClient_.begin(), messageToClient_.end(), '\n'), messageToClient_.end());
}
}
void handle_write(const boost::system::error_code& ec,
size_t bytes_transferred)
{
boost::asio::async_write(socket_,boost::asio::buffer(messageToClient_.data(),bytes_transferred),
// boost::asio::transfer_at_least(bytes_transferred),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
bytes_transferred));
boost::system::error_code tc;
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send, tc);
}
tcp::socket socket_;
std::string messageToClient_;
boost::asio::streambuf input_buffer_;
std::string messageFromClient_;
boost::asio::io_service& io;
boost::asio::deadline_timer timer_,timer2_;
};
Run Code Online (Sandbox Code Playgroud)
上述 async_write 的不可预测行为导致我使用 asio::write 。
小智 2
boost::asio::write() 会阻塞,直到数据写入或抛出异常。您的 write() 函数捕获异常,关闭套接字并返回,但并不表明套接字已关闭。然后,您可以在关闭的套接字上调用 shutdown。创建关闭功能。在 write() 中捕获 drop 异常错误,但在 Write() 调用后等待调用 Shutdown。您的逻辑总是在好的或坏的写入时调用 Shutdown()。也不要调用 io.run()。您的 io_service() 已经在运行。
Shutdown()
{
try {
socket_.shutdown(socket_.shutdown_both);
socket_->close();
} catch (std::exception &e)
{
std::cout << "Error Closing Socket" << e.what() << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)