5 // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14 #include <boost/bind.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include <boost/enable_shared_from_this.hpp>
17 #include <boost/asio.hpp>
19 #if defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
21 using boost::asio::ip::tcp
;
22 using boost::asio::windows::overlapped_ptr
;
23 using boost::asio::windows::random_access_handle
;
25 // A wrapper for the TransmitFile overlapped I/O operation.
26 template <typename Handler
>
27 void transmit_file(tcp::socket
& socket
,
28 random_access_handle
& file
, Handler handler
)
30 // Construct an OVERLAPPED-derived object to contain the handler.
31 overlapped_ptr
overlapped(socket
.get_io_service(), handler
);
33 // Initiate the TransmitFile operation.
34 BOOL ok
= ::TransmitFile(socket
.native_handle(),
35 file
.native_handle(), 0, 0, overlapped
.get(), 0, 0);
36 DWORD last_error
= ::GetLastError();
38 // Check if the operation completed immediately.
39 if (!ok
&& last_error
!= ERROR_IO_PENDING
)
41 // The operation completed immediately, so a completion notification needs
42 // to be posted. When complete() is called, ownership of the OVERLAPPED-
43 // derived object passes to the io_service.
44 boost::system::error_code
ec(last_error
,
45 boost::asio::error::get_system_category());
46 overlapped
.complete(ec
, 0);
50 // The operation was successfully initiated, so ownership of the
51 // OVERLAPPED-derived object has passed to the io_service.
57 : public boost::enable_shared_from_this
<connection
>
60 typedef boost::shared_ptr
<connection
> pointer
;
62 static pointer
create(boost::asio::io_service
& io_service
,
63 const std::string
& filename
)
65 return pointer(new connection(io_service
, filename
));
75 boost::system::error_code ec
;
76 file_
.assign(::CreateFile(filename_
.c_str(), GENERIC_READ
, 0, 0,
77 OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, 0), ec
);
80 transmit_file(socket_
, file_
,
81 boost::bind(&connection::handle_write
, shared_from_this(),
82 boost::asio::placeholders::error
,
83 boost::asio::placeholders::bytes_transferred
));
88 connection(boost::asio::io_service
& io_service
, const std::string
& filename
)
89 : socket_(io_service
),
95 void handle_write(const boost::system::error_code
& /*error*/,
96 size_t /*bytes_transferred*/)
98 boost::system::error_code ignored_ec
;
99 socket_
.shutdown(tcp::socket::shutdown_both
, ignored_ec
);
103 std::string filename_
;
104 random_access_handle file_
;
110 server(boost::asio::io_service
& io_service
,
111 unsigned short port
, const std::string
& filename
)
112 : acceptor_(io_service
, tcp::endpoint(tcp::v4(), port
)),
121 connection::pointer new_connection
=
122 connection::create(acceptor_
.get_io_service(), filename_
);
124 acceptor_
.async_accept(new_connection
->socket(),
125 boost::bind(&server::handle_accept
, this, new_connection
,
126 boost::asio::placeholders::error
));
129 void handle_accept(connection::pointer new_connection
,
130 const boost::system::error_code
& error
)
134 new_connection
->start();
140 tcp::acceptor acceptor_
;
141 std::string filename_
;
144 int main(int argc
, char* argv
[])
150 std::cerr
<< "Usage: transmit_file <port> <filename>\n";
154 boost::asio::io_service io_service
;
156 using namespace std
; // For atoi.
157 server
s(io_service
, atoi(argv
[1]), argv
[2]);
161 catch (std::exception
& e
)
163 std::cerr
<< e
.what() << std::endl
;
169 #else // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
170 # error Overlapped I/O not available on this platform
171 #endif // defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR)