Advertisement
Vlad3955

asio_server.cpp

Nov 12th, 2022 (edited)
833
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.31 KB | None | 0 0
  1. #include <iostream>
  2. #include <memory>
  3. #include <utility>
  4. #include <cstdlib>
  5. #include <cwctype>
  6. #include <stdexcept>
  7. #include <boost/asio.hpp>
  8. #include <optional>
  9. #include <vector>
  10. #include <fstream>
  11. #include <string>
  12. #include <filesystem>
  13. #include <thread>
  14.  
  15.  
  16.  using boost::asio::ip::tcp;
  17.  
  18.  const auto buffer_size = 4096;
  19.  namespace fs = std::filesystem;
  20.  
  21.  
  22.  #if defined(_WIN32)
  23.  const wchar_t separ = fs::path::preferred_separator;
  24.  #else
  25.  const wchar_t separ = *reinterpret_cast<const wchar_t*>(&fs::path::preferred_separator);
  26.  #endif
  27.  
  28.  class session
  29.    : public std::enable_shared_from_this<session>
  30.  {
  31.  public:
  32.    session(tcp::socket socket)
  33.      : socket_(std::move(socket))
  34.    {
  35.    }
  36.  
  37.    void start()
  38.    {
  39.      do_read();
  40.    }
  41.  
  42.  private:
  43.  
  44.  
  45.      std::optional<fs::path> recv_file_path()
  46.      {
  47.          auto request_data = std::string(data_);
  48.          if (!request_data.size()) return std::nullopt;
  49.  
  50.          auto cur_path = fs::current_path().wstring();
  51.          auto file_path = fs::weakly_canonical(request_data).wstring();
  52.  
  53.          #if defined(_WIN32)
  54.          std::transform(cur_path.begin(), cur_path.end(), cur_path.begin(),
  55.              [](wchar_t c) { return std::towlower(c); }
  56.          );
  57.          std::transform(file_path.begin(), file_path.end(), file_path.begin(),
  58.              [](wchar_t c) { return std::towlower(c); }
  59.          );
  60.          #endif
  61.          
  62.          if (file_path.find(cur_path) == 0)
  63.          {
  64.              file_path = file_path.substr(cur_path.length());
  65.          }
  66.  
  67.          return fs::weakly_canonical(cur_path + separ + file_path);
  68.      }
  69.  
  70.  
  71.      bool process()
  72.      {
  73.      auto file_to_send = recv_file_path();
  74.      bool result = false;
  75.  
  76.      if (std::nullopt != file_to_send)
  77.      {
  78.          std::cout << "Trying to send " << *file_to_send << "..." << std::endl;
  79.          if (send_file(*file_to_send))
  80.          {
  81.              std::cout << "File was sent." << std::endl;
  82.              do_read();
  83.          }
  84.          else
  85.          {
  86.              std::cerr << "File sending error!" << std::endl;
  87.              do_read();
  88.          }
  89.          result = true;
  90.      }
  91.  
  92.      return result;
  93.      }
  94.  
  95.    
  96.  
  97.      bool send_buffer(const std::vector<char>& buffer)
  98.      {
  99.          const auto size = buffer.size();
  100.  
  101.          auto self(shared_from_this());
  102.          boost::asio::async_write(socket_, boost::asio::buffer(buffer, size),
  103.              [this, self](boost::system::error_code ec, std::size_t length)
  104.              {
  105.                  if (!ec)
  106.                  {
  107.                      std::cout << length << std::endl;
  108.                      std::cout << ec.message() << std::endl;
  109.                      return true;
  110.                  }
  111.              });
  112.          return false;
  113.      }
  114.  
  115.  
  116.      bool send_file(fs::path const& file_path)
  117.      {
  118.          if (!(fs::exists(file_path) && fs::is_regular_file(file_path))) return false;
  119.          std::vector<char> buffer(buffer_size);
  120.          std::ifstream file_stream(file_path, std::ifstream::binary);
  121.  
  122.          if (!file_stream) return false;
  123.  
  124.          std::cout << "Sending file " << file_path << "..." << std::endl;
  125.          while (file_stream)
  126.          {
  127.              file_stream.read(&buffer[0], buffer.size());
  128.              for (auto& b : buffer)
  129.              {
  130.                  std::cout << b;
  131.              }          
  132.              if (!send_buffer(buffer)) return false;
  133.          }
  134.          return true;
  135.      }
  136.  
  137.  
  138.    void do_read()
  139.    {
  140.      auto self(shared_from_this());
  141.      socket_.async_read_some(boost::asio::buffer(data_, max_length),
  142.          [this, self](boost::system::error_code ec, std::size_t length)
  143.          {
  144.            if (!ec)
  145.            {
  146.              std::cout << data_ << " " << length << std::endl;
  147.              //do_write(length);
  148.              process();
  149.            }
  150.          });
  151.    }
  152.  
  153. //   void do_write(std::size_t length)
  154. //   {
  155. //     auto self(shared_from_this());
  156. //     boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
  157. //         [this, self](boost::system::error_code ec, std::size_t /*length*/)
  158. //         {
  159. //           if (!ec)
  160. //           {
  161. //             do_read();
  162. //           }
  163. //         });
  164. //   }
  165.  
  166.    tcp::socket socket_;
  167.    enum { max_length = 1024 };
  168.    char data_[max_length];
  169.  };
  170.  
  171.  
  172.  
  173.  
  174.  class server
  175.  {
  176.  public:
  177.    server(boost::asio::io_context& io_context, short port)
  178.      : acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
  179.    {
  180.      do_accept();
  181.    }
  182.  
  183.  private:
  184.    void do_accept()
  185.    {
  186.      acceptor_.async_accept(
  187.          [this](boost::system::error_code ec, tcp::socket socket)
  188.          {
  189.            if (!ec)
  190.            {
  191.             std::cout << "Client tid = " << std::this_thread::get_id() << std::endl;
  192.              std::make_shared<session>(std::move(socket))->start();
  193.            }
  194.  
  195.            do_accept();
  196.          });
  197.    }
  198.  
  199.    tcp::acceptor acceptor_;
  200.  };
  201.  
  202.  int main(int argc, char* argv[])
  203.  {
  204.    try
  205.    {
  206.      if (argc != 2)
  207.      {
  208.        std::cerr << "Usage: async_tcp_echo_server <port>\n";
  209.        return 1;
  210.      }
  211.  
  212.      boost::asio::io_context io_context;
  213.  
  214.      server s(io_context, std::atoi(argv[1]));
  215.  
  216.      io_context.run();
  217.    }
  218.    catch (std::exception& e)
  219.    {
  220.      std::cerr << "Exception: " << e.what() << "\n";
  221.    }
  222.  
  223.    return 0;
  224.  }
  225.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement