c++ - Boost::Asio synchronous client with timeout -


i´m trying build synchronous ftp client code timeout using thread timeout control. thread started on every transaction , close socket in case of timeout - force syncronous call return error.

so here code:

#include <cstdlib> #include <cstring> #include <iostream> #include <thread> #include <chrono> #include <boost/asio.hpp>  #define timeout_seconds 5 #define max_message_size 4096 using boost::asio::ip::tcp;  enum { max_length = 1024 };  bool timeron;  void socket_timer(tcp::socket& s, int seconds) {     std::chrono::system_clock::time_point start = std::chrono::system_clock::now();      while (timeron)     {         std::chrono::system_clock::time_point = std::chrono::system_clock::now();         auto interval = std::chrono::duration_cast<std::chrono::seconds>(now - start).count();          if (interval > seconds)             break;          std::this_thread::sleep_for(std::chrono::milliseconds(10)); //  not run in 100% cpu     }       if (timeron)         s.close(); }  void start_timer(int seconds, tcp::socket& s)  {     timeron = true;     std::thread t(socket_timer, s, seconds);     t.detach(); }  void stop_timer() {     timeron = false; }  int main(int argc, char* argv[]) {   std::string address;    while(address != "end")   {       try       {         boost::asio::io_service io_service;          std::cout << "enter ftp server address connect or end finish: " << std::endl;         std::cin >> address;          if (address == "end")             break;          tcp::socket s(io_service);         tcp::resolver resolver(io_service);         boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(address), 21);          start_timer(timeout_seconds, s);         boost::system::error_code ec;         s.connect(endpoint, ec);         stop_timer();          if (ec)         {             throw std::runtime_error("error connecting server.");         }          std::cout << "connected " << s.remote_endpoint().address().to_string() << std::endl;          char reply[max_length];          start_timer(timeout_seconds, s);         size_t bytes = s.receive(boost::asio::buffer(reply, max_message_size), 0, ec);         stop_timer();          if (ec)         {             throw std::runtime_error("error receiving message.");         }          std::cout << "received message is: ";         std::cout.write(reply, bytes);         std::cout << "\n";          std::cout << "enter message: ";         char request[max_length];         std::cin.getline(request, max_length);         size_t request_length = std::strlen(request);          start_timer(timeout_seconds, s);         boost::asio::write(s, boost::asio::buffer(request, request_length));         stop_timer();          if (ec)         {             throw std::runtime_error("error sending message.");         }       }       catch (std::exception& e)       {         std::cerr << "communications error." << "\n";         std::cerr << "exception: " << e.what() << "\n";       }     }     return 0; } 

i cannot compile code, boost showing me following error:

1>------ build started: project: testasio, configuration: debug win32 ------ 1>  main.cpp 1>c:\boost_1_60\boost\asio\basic_socket.hpp(1513): error c2248: 'boost::asio::basic_io_object<ioobjectservice>::basic_io_object' : cannot access private member declared in class 'boost::asio::basic_io_object<ioobjectservice>' 1>          1>          [ 1>              ioobjectservice=boost::asio::stream_socket_service<boost::asio::ip::tcp> 1>          ] 1>          c:\boost_1_60\boost\asio\basic_io_object.hpp(230) : see declaration of 'boost::asio::basic_io_object<ioobjectservice>::basic_io_object' 1>          1>          [ 1>              ioobjectservice=boost::asio::stream_socket_service<boost::asio::ip::tcp> 1>          ] 1>          diagnostic occurred in compiler generated function 'boost::asio::basic_socket<protocol,socketservice>::basic_socket(const boost::asio::basic_socket<protocol,socketservice> &)' 1>          1>          [ 1>              protocol=boost::asio::ip::tcp, 1>              socketservice=boost::asio::stream_socket_service<boost::asio::ip::tcp> 1>          ] ========== build: 0 succeeded, 1 failed, 9 up-to-date, 0 skipped ========== 

so, wanna know 2 things:

a) doing wrong in code ?

b) approach of closing socket on parallel thread work timing out socket ? please fell free comment it.

thanks helping.

i've made helper facility asio async operation "synchronously" timeout here, await_operation:

you should able adapt pattern sample.

demo

it took while since wanted test ftp server.

notes:

  • you didn't resolve address (effectively requiring user type in ip address)
  • you didn't make sure commands closed newline
  • you didn't handle kind of input error

fixing these things and using await_operation you'd this:

#include <cstdlib> #include <cstring> #include <iostream> #include <thread> #include <chrono> #include <boost/asio.hpp> #include <boost/asio/high_resolution_timer.hpp>  #define timeout std::chrono::seconds(5) #define max_message_size 4096 using boost::asio::ip::tcp;  enum { max_length = 2048 };  struct service {     using error_code = boost::system::error_code;      template<typename allowtime, typename cancel> void await_operation_ex(allowtime const& deadline_or_duration, cancel&& cancel) {         using namespace boost::asio;          ioservice.reset();         {             high_resolution_timer tm(ioservice, deadline_or_duration);             tm.async_wait([&cancel](error_code ec) { if (ec != error::operation_aborted) std::forward<cancel>(cancel)(); });             ioservice.run_one();         }         ioservice.run();     }      template<typename allowtime, typename serviceobject> void await_operation(allowtime const& deadline_or_duration, serviceobject& so) {         return await_operation_ex(deadline_or_duration, [&so]{ so.cancel(); });     }      boost::asio::io_service ioservice; };  int main() {   while(true)   {     try     {       service service;        std::cout << "enter ftp server address connect or end finish: " << std::endl;        std::string address;       if (std::cin >> address) {         if (address == "end") break;       } else {         if (std::cin.eof())           break;         std::cerr << "invalid input ignored\n";         std::cin.clear();         std::cin.ignore(1024, '\n');          continue;       }        tcp::socket s(service.ioservice);       tcp::resolver resolver(service.ioservice);        boost::asio::async_connect(s, resolver.resolve({address, "21"}), [](boost::system::error_code ec, tcp::resolver::iterator it) {             if (ec) throw std::runtime_error("error connecting server: " + ec.message());             std::cout << "connected " << it->endpoint() << std::endl;           });       service.await_operation_ex(timeout, [&]{             throw std::runtime_error("error connecting server: timeout\n");           });        auto receive = [&] {         boost::asio::streambuf sb;         size_t bytes;          boost::asio::async_read_until(s, sb, '\n', [&](boost::system::error_code ec, size_t bytes_transferred) {               if (ec) throw std::runtime_error("error receiving message: " + ec.message());               bytes = bytes_transferred;                std::cout << "received message is: " << &sb;             });          service.await_operation(timeout, s);         return bytes;       };        receive(); // banner        auto send = [&](std::string cmd) {         boost::asio::async_write(s, boost::asio::buffer(cmd), [](boost::system::error_code ec, size_t /*bytes_transferred*/) {               if (ec) throw std::runtime_error("error sending message: " + ec.message());             });         service.await_operation(timeout, s);       };        auto ftp_command = [&](std::string cmd) {         send(cmd + "\r\n");         receive(); // response       };        //ftp_command("user bob");       //ftp_command("pass hello");        while (true) {         std::cout << "enter command: ";          std::string request;         if (!std::getline(std::cin, request))           break;          ftp_command(request);       }      }     catch (std::exception const& e)     {       std::cerr << "communications error " << e.what() << "\n";     }   }    return 0; } 

which, in test run, prints e.g.:

enter image description here


Comments

Popular posts from this blog

Command prompt result in label. Python 2.7 -

javascript - How do I use URL parameters to change link href on page? -

amazon web services - AWS Route53 Trying To Get Site To Resolve To www -