#ifdef _WIN32 # define _WIN32_WINNT 0x0501 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include //! tcp_connection /*! * We will use shared_ptr and enable_shared_from_this because we want to keep the * tcp_connection object alive as long as there is an operation that refers to it. */ class tcp_connection : public boost::enable_shared_from_this { public: typedef boost::shared_ptr pointer; static pointer create(boost::asio::io_service& io_service) { return pointer(new tcp_connection(io_service)); } boost::asio::ip::tcp::socket& socket() { return socket_; } void start() { boost::asio::async_read(socket_, boost::asio::buffer(buffer_), boost::bind(&tcp_connection::read_handler, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void read_handler(const boost::system::error_code &ec, std::size_t bytes_transferred) { if (!ec || ec == boost::asio::error::eof) { std::string data(buffer_.data(), bytes_transferred); if (filename_.empty()) { std::istringstream iss(data); std::getline(iss, filename_); file_ = data; file_.erase(0, filename_.size() + 1); filename_ = boost::filesystem::path(filename_).filename(); } else { file_ += data; } if (!ec) boost::asio::async_read(socket_, boost::asio::buffer(buffer_), boost::bind(&tcp_connection::read_handler, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); else { std::ofstream ofs(filename_.c_str(), std::ios::out | std::ios::binary); if (ofs) { ofs << file_; std::cout << filename_ << " received from " << socket_.remote_endpoint() << std::endl; } else std::cerr << filename_ << " couldn't be created" << std::endl; } } else std::cerr << "read_handler error: " << ec << " - " << ec.message() << std::endl; } private: tcp_connection(boost::asio::io_service& io_service) : socket_(io_service) { } std::string filename_; std::string file_; boost::asio::ip::tcp::socket socket_; boost::array buffer_; }; class tcp_server { public: //! An acceptor is initialised in the constructor to listen on the chosen port. tcp_server(boost::asio::io_service& io_service, unsigned int &port) : acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { start_accept(); } private: //! Create a socket and initiate an asynchronous accept operation to wait for a new connection. void start_accept() { tcp_connection::pointer new_connection = tcp_connection::create(acceptor_.io_service()); acceptor_.async_accept(new_connection->socket(), boost::bind(&tcp_server::handle_accept, this, new_connection, boost::asio::placeholders::error)); } /*! * This is called when the asynchronous accept operation initiated by start_accept() finishes. * It services the client request, and then calls start_accept() to initiate the next accept operation. */ void handle_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error) { if (!error) { new_connection->start(); start_accept(); } else { throw(error); } } boost::asio::ip::tcp::acceptor acceptor_; }; class setup_server { public: setup_server(std::string const & port) { boost::system::error_code ec; std::cout << "Host: " << boost::asio::ip::host_name() << std::endl; std::cout << "Listening on port: " << port << std::endl; boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(), port); boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query,ec); if (ec) { throw(ec); } // Look at what connections we have. boost::asio::ip::tcp::resolver::iterator end; while (it != end) { std::cout << it->endpoint().address() << std::endl; ++it; } unsigned int p = boost::lexical_cast(port); tcp_server server(io_service,p); io_service.run(); } private: }; int main(int argc, const char *argv[]) { if (argc < 2) { std::cerr << argv[0] << " " << std::endl; return 1; } try { setup_server server_setup(argv[1]); } catch (boost::system::error_code ec) { std::cerr << "error: " << ec << " - " << ec.message() << std::endl; return EXIT_FAILURE; } catch (std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }