Crash on TCP server crash when client disconnects when server performs asio :: write operation

Just to test my server, I created 100 requests using the for loop on my client side, and when my server writes the response for the Nth request, I intentionally pressed the + c control button from the client, thats it. The server stops and does not respond, although I try to connect to it using a new connection, can someone advise me how to make my server stable and immune to such an interruption. here is my server:

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_; }; 

here is my tcp connection:

 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(); } } 

see my code below where I used async_write; Please note that the line I want to write has the size: 11279204. but using async_write in the code below, let my client get meaasage, which is more partial, but not complete.

 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_; }; 

the above unpredictable behavior of async_write made me use asio :: write.

+4
source share
1 answer

The boost :: asio :: write () blocks until data is written or an exception is thrown. The write () function throws an exception, closes the socket, and returns, but does not indicate that the socket is closed. Then you cause a shutdown in a closed socket. Create a shutdown function. Catch the exception exception exception in write (), but wait to call "Shutdown after calling Write ()." Your logic always calls Shutdown () on good or bad records. Also do not call io.run (). Your io_service () is already running.

  Shutdown() { try { socket_.shutdown(socket_.shutdown_both); socket_->close(); } catch (std::exception &e) { std::cout << "Error Closing Socket" << e.what() << std::endl; } } 
+1
source

All Articles