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.