Update socket iostreams to adhere to the TS.
diff --git a/asio/include/asio/basic_socket_iostream.hpp b/asio/include/asio/basic_socket_iostream.hpp
index 1ada7ce..ad4759b 100644
--- a/asio/include/asio/basic_socket_iostream.hpp
+++ b/asio/include/asio/basic_socket_iostream.hpp
@@ -36,8 +36,8 @@
 //   explicit basic_socket_iostream(T1 x1, ..., Tn xn)
 //     : std::basic_iostream<char>(
 //         &this->detail::socket_iostream_base<
-//           Protocol ASIO_SVC_TARG, Time,
-//           TimeTraits ASIO_SVC_TARG1>::streambuf_)
+//           Protocol ASIO_SVC_TARG, Clock,
+//           WaitTraits ASIO_SVC_TARG1>::streambuf_)
 //   {
 //     if (rdbuf()->connect(x1, ..., xn) == 0)
 //       this->setstate(std::ios_base::failbit);
@@ -49,8 +49,8 @@
   explicit basic_socket_iostream(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
     : std::basic_iostream<char>( \
         &this->detail::socket_iostream_base< \
-          Protocol ASIO_SVC_TARG, Time, \
-          TimeTraits ASIO_SVC_TARG1>::streambuf_) \
+          Protocol ASIO_SVC_TARG, Clock, \
+          WaitTraits ASIO_SVC_TARG1>::streambuf_) \
   { \
     this->setf(std::ios_base::unitbuf); \
     if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
@@ -86,12 +86,34 @@
 // A separate base class is used to ensure that the streambuf is initialised
 // prior to the basic_socket_iostream's basic_iostream base class.
 template <typename Protocol ASIO_SVC_TPARAM,
-    typename Time, typename TimeTraits ASIO_SVC_TPARAM1>
+    typename Clock, typename WaitTraits ASIO_SVC_TPARAM1>
 class socket_iostream_base
 {
 protected:
+  socket_iostream_base()
+  {
+  }
+
+#if defined(ASIO_HAS_MOVE)
+  socket_iostream_base(socket_iostream_base&& other)
+    : streambuf_(std::move(other.streambuf_))
+  {
+  }
+
+  socket_iostream_base(basic_stream_socket<Protocol> s)
+    : streambuf_(std::move(s))
+  {
+  }
+
+  socket_iostream_base& operator=(socket_iostream_base&& other)
+  {
+    streambuf_ = std::move(other.streambuf_);
+    return *this;
+  }
+#endif // defined(ASIO_HAS_MOVE)
+
   basic_socket_streambuf<Protocol ASIO_SVC_TARG,
-    Time, TimeTraits ASIO_SVC_TARG1> streambuf_;
+    Clock, WaitTraits ASIO_SVC_TARG1> streambuf_;
 };
 
 } // namespace detail
@@ -103,12 +125,12 @@
 template <typename Protocol
     ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
 #if defined(ASIO_HAS_BOOST_DATE_TIME)
-    typename Time = boost::posix_time::ptime,
-    typename TimeTraits = time_traits<Time>
-    ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Time, TimeTraits>)>
+    typename Clock = boost::posix_time::ptime,
+    typename WaitTraits = time_traits<Clock>
+    ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
 #else
-    typename Time = chrono::steady_clock,
-    typename TimeTraits = wait_traits<Time>
+    typename Clock = chrono::steady_clock,
+    typename WaitTraits = wait_traits<Clock>
     ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
 #endif
 class basic_socket_iostream;
@@ -118,42 +140,48 @@
 /// Iostream interface for a socket.
 #if defined(GENERATING_DOCUMENTATION)
 template <typename Protocol,
-    typename Time = chrono::steady_clock,
-    typename TimeTraits = wait_traits<Time> >
+    typename Clock = chrono::steady_clock,
+    typename WaitTraits = wait_traits<Clock> >
 #else // defined(GENERATING_DOCUMENTATION)
 template <typename Protocol ASIO_SVC_TPARAM,
-    typename Time, typename TimeTraits ASIO_SVC_TPARAM1>
+    typename Clock, typename WaitTraits ASIO_SVC_TPARAM1>
 #endif // defined(GENERATING_DOCUMENTATION)
 class basic_socket_iostream
   : private detail::socket_iostream_base<Protocol
-        ASIO_SVC_TARG, Time, TimeTraits ASIO_SVC_TARG1>,
+        ASIO_SVC_TARG, Clock, WaitTraits ASIO_SVC_TARG1>,
     public std::basic_iostream<char>
 {
 private:
   // These typedefs are intended keep this class's implementation independent
-  // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
+  // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
 #if defined(ASIO_HAS_BOOST_DATE_TIME)
-  typedef TimeTraits traits_helper;
+  typedef WaitTraits traits_helper;
 #else
-  typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
+  typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
 #endif
 
 public:
+  /// The protocol type.
+  typedef Protocol protocol_type;
+
   /// The endpoint type.
   typedef typename Protocol::endpoint endpoint_type;
 
+  /// The clock type.
+  typedef Clock clock_type;
+
 #if defined(GENERATING_DOCUMENTATION)
   /// (Deprecated: Use time_point.) The time type.
-  typedef typename TimeTraits::time_type time_type;
+  typedef typename WaitTraits::time_type time_type;
 
   /// The time type.
-  typedef typename TimeTraits::time_point time_point;
+  typedef typename WaitTraits::time_point time_point;
 
   /// (Deprecated: Use duration.) The duration type.
-  typedef typename TimeTraits::duration_type duration_type;
+  typedef typename WaitTraits::duration_type duration_type;
 
   /// The duration type.
-  typedef typename TimeTraits::duration duration;
+  typedef typename WaitTraits::duration duration;
 #else
 # if !defined(ASIO_NO_DEPRECATED)
   typedef typename traits_helper::time_type time_type;
@@ -167,12 +195,49 @@
   basic_socket_iostream()
     : std::basic_iostream<char>(
         &this->detail::socket_iostream_base<
-          Protocol ASIO_SVC_TARG, Time,
-          TimeTraits ASIO_SVC_TARG1>::streambuf_)
+          Protocol ASIO_SVC_TARG, Clock,
+          WaitTraits ASIO_SVC_TARG1>::streambuf_)
   {
     this->setf(std::ios_base::unitbuf);
   }
 
+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Construct a basic_socket_iostream from the supplied socket.
+  explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
+    : detail::socket_iostream_base<
+        Protocol ASIO_SVC_TARG, Clock,
+        WaitTraits ASIO_SVC_TARG1>(std::move(s)),
+      std::basic_iostream<char>(
+        &this->detail::socket_iostream_base<
+          Protocol ASIO_SVC_TARG, Clock,
+          WaitTraits ASIO_SVC_TARG1>::streambuf_)
+  {
+    this->setf(std::ios_base::unitbuf);
+  }
+
+  /// Move-construct a basic_socket_iostream from another.
+  basic_socket_iostream(basic_socket_iostream&& other)
+    : detail::socket_iostream_base<
+        Protocol ASIO_SVC_TARG, Clock,
+        WaitTraits ASIO_SVC_TARG1>(std::move(other)),
+      std::basic_iostream<char>(std::move(other))
+  {
+    this->set_rdbuf(&this->detail::socket_iostream_base<
+          Protocol ASIO_SVC_TARG, Clock,
+          WaitTraits ASIO_SVC_TARG1>::streambuf_);
+  }
+
+  /// Move-assign a basic_socket_iostream from another.
+  basic_socket_iostream& operator=(basic_socket_iostream&& other)
+  {
+    std::basic_iostream<char>::operator=(std::move(other));
+    detail::socket_iostream_base<
+        Protocol ASIO_SVC_TARG, Clock,
+        WaitTraits ASIO_SVC_TARG1>::operator=(std::move(other));
+    return *this;
+  }
+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
 #if defined(GENERATING_DOCUMENTATION)
   /// Establish a connection to an endpoint corresponding to a resolver query.
   /**
@@ -187,8 +252,8 @@
   explicit basic_socket_iostream(T... x)
     : std::basic_iostream<char>(
         &this->detail::socket_iostream_base<
-          Protocol ASIO_SVC_TARG, Time,
-          TimeTraits ASIO_SVC_TARG1>::streambuf_)
+          Protocol ASIO_SVC_TARG, Clock,
+          WaitTraits ASIO_SVC_TARG1>::streambuf_)
   {
     this->setf(std::ios_base::unitbuf);
     if (rdbuf()->connect(x...) == 0)
@@ -227,13 +292,13 @@
 
   /// Return a pointer to the underlying streambuf.
   basic_socket_streambuf<Protocol ASIO_SVC_TARG,
-    Time, TimeTraits ASIO_SVC_TARG1>* rdbuf() const
+    Clock, WaitTraits ASIO_SVC_TARG1>* rdbuf() const
   {
     return const_cast<basic_socket_streambuf<Protocol ASIO_SVC_TARG,
-      Time, TimeTraits ASIO_SVC_TARG1>*>(
+      Clock, WaitTraits ASIO_SVC_TARG1>*>(
         &this->detail::socket_iostream_base<
-          Protocol ASIO_SVC_TARG, Time,
-          TimeTraits ASIO_SVC_TARG1>::streambuf_);
+          Protocol ASIO_SVC_TARG, Clock,
+          WaitTraits ASIO_SVC_TARG1>::streambuf_);
   }
 
   /// Get a reference to the underlying socket.
@@ -333,6 +398,12 @@
     rdbuf()->expires_from_now(expiry_time);
   }
 #endif // !defined(ASIO_NO_DEPRECATED)
+
+private:
+  // Disallow copying and assignment.
+  basic_socket_iostream(const basic_socket_iostream&) ASIO_DELETED;
+  basic_socket_iostream& operator=(
+      const basic_socket_iostream&) ASIO_DELETED;
 };
 
 } // namespace asio
diff --git a/asio/include/asio/basic_socket_streambuf.hpp b/asio/include/asio/basic_socket_streambuf.hpp
index 01821ec..42fb3ca 100644
--- a/asio/include/asio/basic_socket_streambuf.hpp
+++ b/asio/include/asio/basic_socket_streambuf.hpp
@@ -20,8 +20,11 @@
 #if !defined(ASIO_NO_IOSTREAM)
 
 #include <streambuf>
+#include <vector>
 #include "asio/basic_socket.hpp"
-#include "asio/detail/array.hpp"
+#include "asio/basic_stream_socket.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/memory.hpp"
 #include "asio/detail/throw_error.hpp"
 #include "asio/io_context.hpp"
 
@@ -48,9 +51,8 @@
 //   basic_socket_streambuf* connect(T1 x1, ..., Tn xn)
 //   {
 //     init_buffers();
-//     this->basic_socket<Protocol ASIO_SVC_TARG>::close(ec_);
 //     typedef typename Protocol::resolver resolver_type;
-//     resolver_type resolver(detail::socket_streambuf_base::io_context_);
+//     resolver_type resolver(socket().get_executor().context());
 //     connect_to_endpoints(
 //         resolver.resolve(x1, ..., xn, ec_));
 //     return !ec_ ? this : 0;
@@ -62,9 +64,8 @@
   basic_socket_streambuf* connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \
   { \
     init_buffers(); \
-    this->basic_socket<Protocol ASIO_SVC_TARG>::close(ec_); \
     typedef typename Protocol::resolver resolver_type; \
-    resolver_type resolver(detail::socket_streambuf_base::io_context_); \
+    resolver_type resolver(socket().get_executor().context()); \
     connect_to_endpoints( \
         resolver.resolve(ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \
     return !ec_ ? this : 0; \
@@ -82,12 +83,36 @@
 namespace asio {
 namespace detail {
 
-// A separate base class is used to ensure that the io_context is initialised
-// prior to the basic_socket_streambuf's basic_socket base class.
-class socket_streambuf_base
+// A separate base class is used to ensure that the io_context member is
+// initialised prior to the basic_socket_streambuf's basic_socket base class.
+class socket_streambuf_io_context
 {
 protected:
-  io_context io_context_;
+  socket_streambuf_io_context(io_context* ctx)
+    : default_io_context_(ctx)
+  {
+  }
+
+  shared_ptr<io_context> default_io_context_;
+};
+
+// A separate base class is used to ensure that the dynamically allocated
+// buffers are constructed prior to the basic_socket_streambuf's basic_socket
+// base class. This makes moving the socket is the last potentially throwing
+// step in the streambuf's move constructor, giving the constructor a strong
+// exception safety guarantee.
+class socket_streambuf_buffers
+{
+protected:
+  socket_streambuf_buffers()
+    : get_buffer_(buffer_size),
+      put_buffer_(buffer_size)
+  {
+  }
+
+  enum { buffer_size = 512 };
+  std::vector<char> get_buffer_;
+  std::vector<char> put_buffer_;
 };
 
 } // namespace detail
@@ -99,12 +124,12 @@
 template <typename Protocol
     ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
 #if defined(ASIO_HAS_BOOST_DATE_TIME)
-    typename Time = boost::posix_time::ptime,
-    typename TimeTraits = time_traits<Time>
-    ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Time, TimeTraits>)>
+    typename Clock = boost::posix_time::ptime,
+    typename WaitTraits = time_traits<Clock>
+    ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
 #else
-    typename Time = chrono::steady_clock,
-    typename TimeTraits = wait_traits<Time>
+    typename Clock = chrono::steady_clock,
+    typename WaitTraits = wait_traits<Clock>
     ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
 #endif
 class basic_socket_streambuf;
@@ -114,15 +139,16 @@
 /// Iostream streambuf for a socket.
 #if defined(GENERATING_DOCUMENTATION)
 template <typename Protocol,
-    typename Time = chrono::steady_clock,
-    typename TimeTraits = wait_traits<Time> >
+    typename Clock = chrono::steady_clock,
+    typename WaitTraits = wait_traits<Clock> >
 #else // defined(GENERATING_DOCUMENTATION)
 template <typename Protocol ASIO_SVC_TPARAM,
-    typename Time, typename TimeTraits ASIO_SVC_TPARAM1>
+    typename Clock, typename WaitTraits ASIO_SVC_TPARAM1>
 #endif // defined(GENERATING_DOCUMENTATION)
 class basic_socket_streambuf
   : public std::streambuf,
-    private detail::socket_streambuf_base,
+    private detail::socket_streambuf_io_context,
+    private detail::socket_streambuf_buffers,
 #if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
     private basic_socket<Protocol ASIO_SVC_TARG>
 #else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
@@ -131,29 +157,35 @@
 {
 private:
   // These typedefs are intended keep this class's implementation independent
-  // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
+  // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
 #if defined(ASIO_HAS_BOOST_DATE_TIME)
-  typedef TimeTraits traits_helper;
+  typedef WaitTraits traits_helper;
 #else
-  typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
+  typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
 #endif
 
 public:
+  /// The protocol type.
+  typedef Protocol protocol_type;
+
   /// The endpoint type.
   typedef typename Protocol::endpoint endpoint_type;
 
+  /// The clock type.
+  typedef Clock clock_type;
+
 #if defined(GENERATING_DOCUMENTATION)
   /// (Deprecated: Use time_point.) The time type.
-  typedef typename TimeTraits::time_type time_type;
+  typedef typename WaitTraits::time_type time_type;
 
   /// The time type.
-  typedef typename TimeTraits::time_point time_point;
+  typedef typename WaitTraits::time_point time_point;
 
   /// (Deprecated: Use duration.) The duration type.
-  typedef typename TimeTraits::duration_type duration_type;
+  typedef typename WaitTraits::duration_type duration_type;
 
   /// The duration type.
-  typedef typename TimeTraits::duration duration;
+  typedef typename WaitTraits::duration duration;
 #else
 # if !defined(ASIO_NO_DEPRECATED)
   typedef typename traits_helper::time_type time_type;
@@ -165,22 +197,64 @@
 
   /// Construct a basic_socket_streambuf without establishing a connection.
   basic_socket_streambuf()
-    : basic_socket<Protocol ASIO_SVC_TARG>(
-        this->detail::socket_streambuf_base::io_context_),
-      unbuffered_(false),
-      timer_service_(0),
-      timer_state_(no_timer)
+    : detail::socket_streambuf_io_context(new io_context),
+      basic_socket<Protocol ASIO_SVC_TARG>(*default_io_context_),
+      expiry_time_(max_expiry_time())
   {
     init_buffers();
   }
 
+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Construct a basic_socket_streambuf from the supplied socket.
+  explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s)
+    : detail::socket_streambuf_io_context(0),
+      basic_socket<Protocol ASIO_SVC_TARG>(std::move(s)),
+      expiry_time_(max_expiry_time())
+  {
+    init_buffers();
+  }
+
+  /// Move-construct a basic_socket_streambuf from another.
+  basic_socket_streambuf(basic_socket_streambuf&& other)
+    : detail::socket_streambuf_io_context(other),
+      basic_socket<Protocol ASIO_SVC_TARG>(std::move(other.socket())),
+      ec_(other.ec_),
+      expiry_time_(other.expiry_time_)
+  {
+    get_buffer_.swap(other.get_buffer_);
+    put_buffer_.swap(other.put_buffer_);
+    setg(other.eback(), other.gptr(), other.egptr());
+    setp(other.pptr(), other.epptr());
+    other.ec_ = asio::error_code();
+    other.expiry_time_ = max_expiry_time();
+    other.init_buffers();
+  }
+
+  /// Move-assign a basic_socket_streambuf from another.
+  basic_socket_streambuf& operator=(basic_socket_streambuf&& other)
+  {
+    this->close();
+    socket() = std::move(other.socket());
+    detail::socket_streambuf_io_context::operator=(other);
+    ec_ = other.ec_;
+    expiry_time_ = other.expiry_time_;
+    get_buffer_.swap(other.get_buffer_);
+    put_buffer_.swap(other.put_buffer_);
+    setg(other.eback(), other.gptr(), other.egptr());
+    setp(other.pptr(), other.epptr());
+    other.ec_ = asio::error_code();
+    other.expiry_time_ = max_expiry_time();
+    other.put_buffer_.resize(buffer_size);
+    other.init_buffers();
+    return *this;
+  }
+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
   /// Destructor flushes buffered data.
   virtual ~basic_socket_streambuf()
   {
     if (pptr() != pbase())
       overflow(traits_type::eof());
-
-    destroy_timer();
   }
 
   /// Establish a connection.
@@ -193,24 +267,8 @@
   basic_socket_streambuf* connect(const endpoint_type& endpoint)
   {
     init_buffers();
-
-    this->basic_socket<Protocol ASIO_SVC_TARG>::close(ec_);
-
-    if (timer_state_ == timer_has_expired)
-    {
-      ec_ = asio::error::operation_aborted;
-      return 0;
-    }
-
-    io_handler handler = { this };
-    this->basic_socket<Protocol ASIO_SVC_TARG>::async_connect(
-        endpoint, handler);
-
-    ec_ = asio::error::would_block;
-    this->get_service().get_io_context().restart();
-    do this->get_service().get_io_context().run_one();
-    while (ec_ == asio::error::would_block);
-
+    ec_ = asio::error_code();
+    this->connect_to_endpoints(&endpoint, &endpoint + 1);
     return !ec_ ? this : 0;
   }
 
@@ -231,9 +289,8 @@
   basic_socket_streambuf* connect(T... x)
   {
     init_buffers();
-    this->basic_socket<Protocol ASIO_SVC_TARG>::close(ec_);
     typedef typename Protocol::resolver resolver_type;
-    resolver_type resolver(detail::socket_streambuf_base::io_context_);
+    resolver_type resolver(socket().get_executor().context());
     connect_to_endpoints(resolver.resolve(x..., ec_));
     return !ec_ ? this : 0;
   }
@@ -249,7 +306,7 @@
   basic_socket_streambuf* close()
   {
     sync();
-    this->basic_socket<Protocol ASIO_SVC_TARG>::close(ec_);
+    socket().close(ec_);
     if (!ec_)
       init_buffers();
     return !ec_ ? this : 0;
@@ -291,9 +348,7 @@
    */
   time_point expires_at() const
   {
-    return timer_service_
-      ? timer_service_->expires_at(timer_implementation_)
-      : time_point();
+    return expiry_time_;
   }
 #endif // !defined(ASIO_NO_DEPRECATED)
 
@@ -304,13 +359,7 @@
    */
   time_point expiry() const
   {
-    return timer_service_
-#if defined(ASIO_HAS_BOOST_DATE_TIME)
-      ? timer_service_->expires_at(timer_implementation_)
-#else // defined(ASIO_HAS_BOOST_DATE_TIME)
-      ? timer_service_->expiry(timer_implementation_)
-#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
-      : time_point();
+    return expiry_time_;
   }
 
   /// Set the stream buffer's expiry time as an absolute time.
@@ -324,13 +373,7 @@
    */
   void expires_at(const time_point& expiry_time)
   {
-    construct_timer();
-
-    asio::error_code ec;
-    timer_service_->expires_at(timer_implementation_, expiry_time, ec);
-    asio::detail::throw_error(ec, "expires_at");
-
-    start_timer();
+    expiry_time_ = expiry_time;
   }
 
   /// Set the stream buffer's expiry time relative to now.
@@ -344,17 +387,7 @@
    */
   void expires_after(const duration& expiry_time)
   {
-    construct_timer();
-
-    asio::error_code ec;
-#if defined(ASIO_HAS_BOOST_DATE_TIME)
-    timer_service_->expires_from_now(timer_implementation_, expiry_time, ec);
-#else // defined(ASIO_HAS_BOOST_DATE_TIME)
-    timer_service_->expires_after(timer_implementation_, expiry_time, ec);
-#endif // defined(ASIO_HAS_BOOST_DATE_TIME)
-    asio::detail::throw_error(ec, "expires_after");
-
-    start_timer();
+    expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
   }
 
 #if !defined(ASIO_NO_DEPRECATED)
@@ -380,108 +413,124 @@
    */
   void expires_from_now(const duration& expiry_time)
   {
-    construct_timer();
-
-    asio::error_code ec;
-    timer_service_->expires_from_now(timer_implementation_, expiry_time, ec);
-    asio::detail::throw_error(ec, "expires_from_now");
-
-    start_timer();
+    expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
   }
 #endif // !defined(ASIO_NO_DEPRECATED)
 
 protected:
   int_type underflow()
   {
-    if (gptr() == egptr())
+#if defined(ASIO_WINDOWS_RUNTIME)
+    ec_ = asio::error::operation_not_supported;
+    return traits_type::eof();
+#else // defined(ASIO_WINDOWS_RUNTIME)
+    if (gptr() != egptr())
+      return traits_type::eof();
+
+    for (;;)
     {
-      if (timer_state_ == timer_has_expired)
+      // Check if we are past the expiry time.
+      if (traits_helper::less_than(expiry_time_, traits_helper::now()))
       {
-        ec_ = asio::error::operation_aborted;
+        ec_ = asio::error::timed_out;
         return traits_type::eof();
       }
 
-      io_handler handler = { this };
-      this->get_service().async_receive(this->get_implementation(),
-          asio::buffer(asio::buffer(get_buffer_) + putback_max),
-          0, handler);
+      // Try to complete the operation without blocking.
+      if (!socket().native_non_blocking())
+        socket().native_non_blocking(true, ec_);
+      detail::buffer_sequence_adapter<mutable_buffer, mutable_buffer>
+        bufs(asio::buffer(get_buffer_) + putback_max);
+      detail::signed_size_type bytes = detail::socket_ops::recv(
+          socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
 
-      ec_ = asio::error::would_block;
-      this->get_service().get_io_context().restart();
-      do this->get_service().get_io_context().run_one();
-      while (ec_ == asio::error::would_block);
-      if (ec_)
+      // Check if operation succeeded.
+      if (bytes > 0)
+      {
+        setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
+            &get_buffer_[0] + putback_max + bytes);
+        return traits_type::to_int_type(*gptr());
+      }
+
+      // Check for EOF.
+      if (bytes == 0)
+      {
+        ec_ = asio::error::eof;
+        return traits_type::eof();
+      }
+
+      // Operation failed.
+      if (ec_ != asio::error::would_block
+          && ec_ != asio::error::try_again)
         return traits_type::eof();
 
-      setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
-          &get_buffer_[0] + putback_max + bytes_transferred_);
-      return traits_type::to_int_type(*gptr());
+      // Wait for socket to become ready.
+      if (detail::socket_ops::poll_read(
+            socket().native_handle(), 0, timeout(), ec_) < 0)
+        return traits_type::eof();
     }
-    else
-    {
-      return traits_type::eof();
-    }
+#endif // defined(ASIO_WINDOWS_RUNTIME)
   }
 
   int_type overflow(int_type c)
   {
-    if (unbuffered_)
+#if defined(ASIO_WINDOWS_RUNTIME)
+    ec_ = asio::error::operation_not_supported;
+    return traits_type::eof();
+#else // defined(ASIO_WINDOWS_RUNTIME)
+    char_type ch = traits_type::to_char_type(c);
+
+    // Determine what needs to be sent.
+    const_buffer output_buffer;
+    if (put_buffer_.empty())
     {
       if (traits_type::eq_int_type(c, traits_type::eof()))
-      {
-        // Nothing to do.
-        return traits_type::not_eof(c);
-      }
-      else
-      {
-        if (timer_state_ == timer_has_expired)
-        {
-          ec_ = asio::error::operation_aborted;
-          return traits_type::eof();
-        }
-
-        // Send the single character immediately.
-        char_type ch = traits_type::to_char_type(c);
-        io_handler handler = { this };
-        this->get_service().async_send(this->get_implementation(),
-            asio::buffer(&ch, sizeof(char_type)), 0, handler);
-
-        ec_ = asio::error::would_block;
-        this->get_service().get_io_context().restart();
-        do this->get_service().get_io_context().run_one();
-        while (ec_ == asio::error::would_block);
-        if (ec_)
-          return traits_type::eof();
-
-        return c;
-      }
+        return traits_type::not_eof(c); // Nothing to do.
+      output_buffer = asio::buffer(&ch, sizeof(char_type));
     }
     else
     {
-      // Send all data in the output buffer.
-      asio::const_buffer buffer =
-        asio::buffer(pbase(), pptr() - pbase());
-      while (buffer.size() > 0)
+      output_buffer = asio::buffer(pbase(),
+          (pptr() - pbase()) * sizeof(char_type));
+    }
+
+    while (output_buffer.size() > 0)
+    {
+      // Check if we are past the expiry time.
+      if (traits_helper::less_than(expiry_time_, traits_helper::now()))
       {
-        if (timer_state_ == timer_has_expired)
-        {
-          ec_ = asio::error::operation_aborted;
-          return traits_type::eof();
-        }
-
-        io_handler handler = { this };
-        this->get_service().async_send(this->get_implementation(),
-            asio::buffer(buffer), 0, handler);
-
-        ec_ = asio::error::would_block;
-        this->get_service().get_io_context().restart();
-        do this->get_service().get_io_context().run_one();
-        while (ec_ == asio::error::would_block);
-        if (ec_)
-          return traits_type::eof();
-
-        buffer = buffer + bytes_transferred_;
+        ec_ = asio::error::timed_out;
+        return traits_type::eof();
       }
+
+      // Try to complete the operation without blocking.
+      if (!socket().native_non_blocking())
+        socket().native_non_blocking(true, ec_);
+      detail::buffer_sequence_adapter<
+        const_buffer, const_buffer> bufs(output_buffer);
+      detail::signed_size_type bytes = detail::socket_ops::send(
+          socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
+
+      // Check if operation succeeded.
+      if (bytes > 0)
+      {
+        output_buffer += static_cast<std::size_t>(bytes);
+        continue;
+      }
+
+      // Operation failed.
+      if (ec_ != asio::error::would_block
+          && ec_ != asio::error::try_again)
+        return traits_type::eof();
+
+      // Wait for socket to become ready.
+      if (detail::socket_ops::poll_write(
+            socket().native_handle(), 0, timeout(), ec_) < 0)
+        return traits_type::eof();
+    }
+
+    if (!put_buffer_.empty())
+    {
       setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
 
       // If the new character is eof then our work here is done.
@@ -489,10 +538,12 @@
         return traits_type::not_eof(c);
 
       // Add the new character to the output buffer.
-      *pptr() = traits_type::to_char_type(c);
+      *pptr() = ch;
       pbump(1);
-      return c;
     }
+
+    return c;
+#endif // defined(ASIO_WINDOWS_RUNTIME)
   }
 
   int sync()
@@ -504,8 +555,9 @@
   {
     if (pptr() == pbase() && s == 0 && n == 0)
     {
-      unbuffered_ = true;
+      put_buffer_.clear();
       setp(0, 0);
+      sync();
       return this;
     }
 
@@ -513,131 +565,117 @@
   }
 
 private:
+  // Disallow copying and assignment.
+  basic_socket_streambuf(const basic_socket_streambuf&) ASIO_DELETED;
+  basic_socket_streambuf& operator=(
+      const basic_socket_streambuf&) ASIO_DELETED;
+
   void init_buffers()
   {
     setg(&get_buffer_[0],
         &get_buffer_[0] + putback_max,
         &get_buffer_[0] + putback_max);
-    if (unbuffered_)
+
+    if (put_buffer_.empty())
       setp(0, 0);
     else
       setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
   }
 
+  int timeout() const
+  {
+    int64_t msec = traits_helper::to_posix_duration(
+        traits_helper::subtract(expiry_time_,
+          traits_helper::now())).total_milliseconds();
+    if (msec > (std::numeric_limits<int>::max)())
+      msec = (std::numeric_limits<int>::max)();
+    else if (msec < 0)
+      msec = 0;
+    return static_cast<int>(msec);
+  }
+
   template <typename EndpointSequence>
   void connect_to_endpoints(const EndpointSequence& endpoints)
   {
-    if (!ec_)
-    {
-      typename EndpointSequence::iterator i = endpoints.begin();
-      typename EndpointSequence::iterator end = endpoints.end();
-      ec_ = asio::error::host_not_found;
-      while (ec_ && i != end)
-      {
-        this->basic_socket<Protocol ASIO_SVC_TARG>::close(ec_);
-
-        if (timer_state_ == timer_has_expired)
-        {
-          ec_ = asio::error::operation_aborted;
-          return;
-        }
-
-        io_handler handler = { this };
-        this->basic_socket<Protocol ASIO_SVC_TARG>::async_connect(
-            *i, handler);
-
-        ec_ = asio::error::would_block;
-        this->get_service().get_io_context().restart();
-        do this->get_service().get_io_context().run_one();
-        while (ec_ == asio::error::would_block);
-
-        ++i;
-      }
-    }
+    this->connect_to_endpoints(endpoints.begin(), endpoints.end());
   }
 
-  struct io_handler;
-  friend struct io_handler;
-  struct io_handler
+  template <typename EndpointIterator>
+  void connect_to_endpoints(EndpointIterator begin, EndpointIterator end)
   {
-    basic_socket_streambuf* this_;
+#if defined(ASIO_WINDOWS_RUNTIME)
+    ec_ = asio::error::operation_not_supported;
+#else // defined(ASIO_WINDOWS_RUNTIME)
+    if (ec_)
+      return;
 
-    void operator()(const asio::error_code& ec,
-        std::size_t bytes_transferred = 0)
+    ec_ = asio::error::not_found;
+    for (EndpointIterator i = begin; i != end; ++i)
     {
-      this_->ec_ = ec;
-      this_->bytes_transferred_ = bytes_transferred;
+      // Check if we are past the expiry time.
+      if (traits_helper::less_than(expiry_time_, traits_helper::now()))
+      {
+        ec_ = asio::error::timed_out;
+        return;
+      }
+
+      // Close and reopen the socket.
+      typename Protocol::endpoint ep(*i);
+      socket().close(ec_);
+      socket().open(ep.protocol(), ec_);
+      if (ec_)
+        continue;
+
+      // Try to complete the operation without blocking.
+      if (!socket().native_non_blocking())
+        socket().native_non_blocking(true, ec_);
+      detail::socket_ops::connect(socket().native_handle(),
+          ep.data(), ep.size(), ec_);
+
+      // Check if operation succeeded.
+      if (!ec_)
+        return;
+
+      // Operation failed.
+      if (ec_ != asio::error::in_progress
+          && ec_ != asio::error::would_block)
+        continue;
+
+      // Wait for socket to become ready.
+      if (detail::socket_ops::poll_connect(
+            socket().native_handle(), timeout(), ec_) < 0)
+        continue;
+
+      // Get the error code from the connect operation.
+      int connect_error = 0;
+      size_t connect_error_len = sizeof(connect_error);
+      if (detail::socket_ops::getsockopt(socket().native_handle(), 0,
+            SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec_)
+          == detail::socket_error_retval)
+        return;
+
+      // Check the result of the connect operation.
+      ec_ = asio::error_code(connect_error,
+          asio::error::get_system_category());
+      if (!ec_)
+        return;
     }
-  };
+#endif // defined(ASIO_WINDOWS_RUNTIME)
+  }
 
-  struct timer_handler;
-  friend struct timer_handler;
-  struct timer_handler
+  // Helper function to get the maximum expiry time.
+  static time_point max_expiry_time()
   {
-    basic_socket_streambuf* this_;
-
-    void operator()(const asio::error_code&)
-    {
-      time_point now = traits_helper::now();
-
 #if defined(ASIO_HAS_BOOST_DATE_TIME)
-      time_point expiry_time = this_->timer_service_->expires_at(
-            this_->timer_implementation_);
+    return boost::posix_time::pos_infin;
 #else // defined(ASIO_HAS_BOOST_DATE_TIME)
-      time_point expiry_time = this_->timer_service_->expiry(
-            this_->timer_implementation_);
+    return (time_point::max)();
 #endif // defined(ASIO_HAS_BOOST_DATE_TIME)
-
-      if (traits_helper::less_than(now, expiry_time))
-      {
-        this_->timer_state_ = timer_is_pending;
-        this_->timer_service_->async_wait(this_->timer_implementation_, *this);
-      }
-      else
-      {
-        this_->timer_state_ = timer_has_expired;
-        asio::error_code ec;
-        this_->basic_socket<Protocol ASIO_SVC_TARG>::close(ec);
-      }
-    }
-  };
-
-  void construct_timer()
-  {
-    if (timer_service_ == 0)
-    {
-      ASIO_SVC_T1& timer_service = use_service<ASIO_SVC_T1>(
-          detail::socket_streambuf_base::io_context_);
-      timer_service.construct(timer_implementation_);
-      timer_service_ = &timer_service;
-    }
-  }
-
-  void destroy_timer()
-  {
-    if (timer_service_)
-      timer_service_->destroy(timer_implementation_);
-  }
-
-  void start_timer()
-  {
-    if (timer_state_ != timer_is_pending)
-    {
-      timer_handler handler = { this };
-      handler(asio::error_code());
-    }
   }
 
   enum { putback_max = 8 };
-  enum { buffer_size = 512 };
-  asio::detail::array<char, buffer_size> get_buffer_;
-  asio::detail::array<char, buffer_size> put_buffer_;
-  bool unbuffered_;
   asio::error_code ec_;
-  std::size_t bytes_transferred_;
-  ASIO_SVC_T1* timer_service_;
-  typename ASIO_SVC_T1::implementation_type timer_implementation_;
-  enum state { no_timer, timer_is_pending, timer_has_expired } timer_state_;
+  time_point expiry_time_;
 };
 
 } // namespace asio
diff --git a/asio/include/asio/detail/impl/socket_ops.ipp b/asio/include/asio/detail/impl/socket_ops.ipp
index b643c8b..d9cc1c9 100644
--- a/asio/include/asio/detail/impl/socket_ops.ipp
+++ b/asio/include/asio/detail/impl/socket_ops.ipp
@@ -168,7 +168,7 @@
       return invalid_socket;
 
     // Wait for socket to become ready.
-    if (socket_ops::poll_read(s, 0, ec) < 0)
+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)
       return invalid_socket;
   }
 }
@@ -505,7 +505,7 @@
   }
 
   // Wait for socket to become ready.
-  if (socket_ops::poll_connect(s, ec) < 0)
+  if (socket_ops::poll_connect(s, -1, ec) < 0)
     return;
 
   // Get the error code from the connect operation.
@@ -827,7 +827,7 @@
       return 0;
 
     // Wait for socket to become ready.
-    if (socket_ops::poll_read(s, 0, ec) < 0)
+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)
       return 0;
   }
 }
@@ -966,7 +966,7 @@
       return 0;
 
     // Wait for socket to become ready.
-    if (socket_ops::poll_read(s, 0, ec) < 0)
+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)
       return 0;
   }
 }
@@ -1079,7 +1079,7 @@
       return 0;
 
     // Wait for socket to become ready.
-    if (socket_ops::poll_read(s, 0, ec) < 0)
+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)
       return 0;
   }
 }
@@ -1206,7 +1206,7 @@
       return 0;
 
     // Wait for socket to become ready.
-    if (socket_ops::poll_write(s, 0, ec) < 0)
+    if (socket_ops::poll_write(s, 0, -1, ec) < 0)
       return 0;
   }
 }
@@ -1330,7 +1330,7 @@
       return 0;
 
     // Wait for socket to become ready.
-    if (socket_ops::poll_write(s, 0, ec) < 0)
+    if (socket_ops::poll_write(s, 0, -1, ec) < 0)
       return 0;
   }
 }
@@ -1784,7 +1784,8 @@
 #endif
 }
 
-int poll_read(socket_type s, state_type state, asio::error_code& ec)
+int poll_read(socket_type s, state_type state,
+    int msec, asio::error_code& ec)
 {
   if (s == invalid_socket)
   {
@@ -1798,10 +1799,22 @@
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);
-  timeval zero_timeout;
-  zero_timeout.tv_sec = 0;
-  zero_timeout.tv_usec = 0;
-  timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0;
+  timeval timeout_obj;
+  timeval* timeout;
+  if (state & user_set_non_blocking)
+  {
+    timeout_obj.tv_sec = 0;
+    timeout_obj.tv_usec = 0;
+    timeout = &timeout_obj;
+  }
+  else if (msec >= 0)
+  {
+    timeout_obj.tv_sec = msec / 1000;
+    timeout_obj.tv_usec = (msec % 1000) * 1000;
+    timeout = &timeout_obj;
+  }
+  else
+    timeout = 0;
   clear_last_error();
   int result = error_wrapper(::select(s + 1, &fds, 0, 0, timeout), ec);
 #else // defined(ASIO_WINDOWS)
@@ -1811,7 +1824,7 @@
   fds.fd = s;
   fds.events = POLLIN;
   fds.revents = 0;
-  int timeout = (state & user_set_non_blocking) ? 0 : -1;
+  int timeout = (state & user_set_non_blocking) ? 0 : msec;
   clear_last_error();
   int result = error_wrapper(::poll(&fds, 1, timeout), ec);
 #endif // defined(ASIO_WINDOWS)
@@ -1825,7 +1838,8 @@
   return result;
 }
 
-int poll_write(socket_type s, state_type state, asio::error_code& ec)
+int poll_write(socket_type s, state_type state,
+    int msec, asio::error_code& ec)
 {
   if (s == invalid_socket)
   {
@@ -1839,10 +1853,22 @@
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);
-  timeval zero_timeout;
-  zero_timeout.tv_sec = 0;
-  zero_timeout.tv_usec = 0;
-  timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0;
+  timeval timeout_obj;
+  timeval* timeout;
+  if (state & user_set_non_blocking)
+  {
+    timeout_obj.tv_sec = 0;
+    timeout_obj.tv_usec = 0;
+    timeout = &timeout_obj;
+  }
+  else if (msec >= 0)
+  {
+    timeout_obj.tv_sec = msec / 1000;
+    timeout_obj.tv_usec = (msec % 1000) * 1000;
+    timeout = &timeout_obj;
+  }
+  else
+    timeout = 0;
   clear_last_error();
   int result = error_wrapper(::select(s + 1, 0, &fds, 0, timeout), ec);
 #else // defined(ASIO_WINDOWS)
@@ -1852,7 +1878,7 @@
   fds.fd = s;
   fds.events = POLLOUT;
   fds.revents = 0;
-  int timeout = (state & user_set_non_blocking) ? 0 : -1;
+  int timeout = (state & user_set_non_blocking) ? 0 : msec;
   clear_last_error();
   int result = error_wrapper(::poll(&fds, 1, timeout), ec);
 #endif // defined(ASIO_WINDOWS)
@@ -1866,7 +1892,8 @@
   return result;
 }
 
-int poll_error(socket_type s, state_type state, asio::error_code& ec)
+int poll_error(socket_type s, state_type state,
+    int msec, asio::error_code& ec)
 {
   if (s == invalid_socket)
   {
@@ -1880,10 +1907,22 @@
   fd_set fds;
   FD_ZERO(&fds);
   FD_SET(s, &fds);
-  timeval zero_timeout;
-  zero_timeout.tv_sec = 0;
-  zero_timeout.tv_usec = 0;
-  timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0;
+  timeval timeout_obj;
+  timeval* timeout;
+  if (state & user_set_non_blocking)
+  {
+    timeout_obj.tv_sec = 0;
+    timeout_obj.tv_usec = 0;
+    timeout = &timeout_obj;
+  }
+  else if (msec >= 0)
+  {
+    timeout_obj.tv_sec = msec / 1000;
+    timeout_obj.tv_usec = (msec % 1000) * 1000;
+    timeout = &timeout_obj;
+  }
+  else
+    timeout = 0;
   clear_last_error();
   int result = error_wrapper(::select(s + 1, 0, 0, &fds, timeout), ec);
 #else // defined(ASIO_WINDOWS)
@@ -1893,7 +1932,7 @@
   fds.fd = s;
   fds.events = POLLPRI | POLLERR | POLLHUP;
   fds.revents = 0;
-  int timeout = (state & user_set_non_blocking) ? 0 : -1;
+  int timeout = (state & user_set_non_blocking) ? 0 : msec;
   clear_last_error();
   int result = error_wrapper(::poll(&fds, 1, timeout), ec);
 #endif // defined(ASIO_WINDOWS)
@@ -1907,7 +1946,7 @@
   return result;
 }
 
-int poll_connect(socket_type s, asio::error_code& ec)
+int poll_connect(socket_type s, int msec, asio::error_code& ec)
 {
   if (s == invalid_socket)
   {
@@ -1924,9 +1963,19 @@
   fd_set except_fds;
   FD_ZERO(&except_fds);
   FD_SET(s, &except_fds);
+  timeval timeout_obj;
+  timeval* timeout;
+  if (msec >= 0)
+  {
+    timeout_obj.tv_sec = msec / 1000;
+    timeout_obj.tv_usec = (msec % 1000) * 1000;
+    timeout = &timeout_obj;
+  }
+  else
+    timeout = 0;
   clear_last_error();
   int result = error_wrapper(::select(
-        s + 1, 0, &write_fds, &except_fds, 0), ec);
+        s + 1, 0, &write_fds, &except_fds, timeout), ec);
   if (result >= 0)
     ec = asio::error_code();
   return result;
@@ -1938,7 +1987,7 @@
   fds.events = POLLOUT;
   fds.revents = 0;
   clear_last_error();
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  int result = error_wrapper(::poll(&fds, 1, msec), ec);
   if (result >= 0)
     ec = asio::error_code();
   return result;
diff --git a/asio/include/asio/detail/reactive_socket_service.hpp b/asio/include/asio/detail/reactive_socket_service.hpp
index e12e835..4ba2556 100644
--- a/asio/include/asio/detail/reactive_socket_service.hpp
+++ b/asio/include/asio/detail/reactive_socket_service.hpp
@@ -231,7 +231,7 @@
       asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_write(impl.socket_, impl.state_, ec);
+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
 
     return 0;
   }
@@ -310,7 +310,7 @@
       asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, impl.state_, ec);
+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
 
     // Reset endpoint since it can be given no sensible value at this time.
     sender_endpoint = endpoint_type();
diff --git a/asio/include/asio/detail/reactive_socket_service_base.hpp b/asio/include/asio/detail/reactive_socket_service_base.hpp
index 0d9a767..3b5b014 100644
--- a/asio/include/asio/detail/reactive_socket_service_base.hpp
+++ b/asio/include/asio/detail/reactive_socket_service_base.hpp
@@ -171,13 +171,13 @@
     switch (w)
     {
     case socket_base::wait_read:
-      socket_ops::poll_read(impl.socket_, impl.state_, ec);
+      socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
       break;
     case socket_base::wait_write:
-      socket_ops::poll_write(impl.socket_, impl.state_, ec);
+      socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
       break;
     case socket_base::wait_error:
-      socket_ops::poll_error(impl.socket_, impl.state_, ec);
+      socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
       break;
     default:
       ec = asio::error::invalid_argument;
@@ -246,7 +246,7 @@
       socket_base::message_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_write(impl.socket_, impl.state_, ec);
+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
 
     return 0;
   }
@@ -316,7 +316,7 @@
       socket_base::message_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, impl.state_, ec);
+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
 
     return 0;
   }
@@ -396,7 +396,7 @@
       socket_base::message_flags& out_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, impl.state_, ec);
+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
 
     // Clear out_flags, since we cannot give it any other sensible value when
     // performing a null_buffers operation.
diff --git a/asio/include/asio/detail/socket_ops.hpp b/asio/include/asio/detail/socket_ops.hpp
index 880c8e6..5529a27 100644
--- a/asio/include/asio/detail/socket_ops.hpp
+++ b/asio/include/asio/detail/socket_ops.hpp
@@ -263,15 +263,16 @@
     fd_set* exceptfds, timeval* timeout, asio::error_code& ec);
 
 ASIO_DECL int poll_read(socket_type s,
-    state_type state, asio::error_code& ec);
+    state_type state, int msec, asio::error_code& ec);
 
 ASIO_DECL int poll_write(socket_type s,
-    state_type state, asio::error_code& ec);
+    state_type state, int msec, asio::error_code& ec);
 
 ASIO_DECL int poll_error(socket_type s,
-    state_type state, asio::error_code& ec);
+    state_type state, int msec, asio::error_code& ec);
 
-ASIO_DECL int poll_connect(socket_type s, asio::error_code& ec);
+ASIO_DECL int poll_connect(socket_type s,
+    int msec, asio::error_code& ec);
 
 #endif // !defined(ASIO_WINDOWS_RUNTIME)
 
diff --git a/asio/include/asio/detail/win_iocp_socket_service.hpp b/asio/include/asio/detail/win_iocp_socket_service.hpp
index 787267d..9040f7c 100644
--- a/asio/include/asio/detail/win_iocp_socket_service.hpp
+++ b/asio/include/asio/detail/win_iocp_socket_service.hpp
@@ -315,7 +315,7 @@
       asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_write(impl.socket_, impl.state_, ec);
+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
 
     return 0;
   }
@@ -391,7 +391,7 @@
       socket_base::message_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, impl.state_, ec);
+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
 
     // Reset endpoint since it can be given no sensible value at this time.
     sender_endpoint = endpoint_type();
diff --git a/asio/include/asio/detail/win_iocp_socket_service_base.hpp b/asio/include/asio/detail/win_iocp_socket_service_base.hpp
index c671835..9f22adc 100644
--- a/asio/include/asio/detail/win_iocp_socket_service_base.hpp
+++ b/asio/include/asio/detail/win_iocp_socket_service_base.hpp
@@ -188,13 +188,13 @@
     switch (w)
     {
     case socket_base::wait_read:
-      socket_ops::poll_read(impl.socket_, impl.state_, ec);
+      socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
       break;
     case socket_base::wait_write:
-      socket_ops::poll_write(impl.socket_, impl.state_, ec);
+      socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
       break;
     case socket_base::wait_error:
-      socket_ops::poll_error(impl.socket_, impl.state_, ec);
+      socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
       break;
     default:
       ec = asio::error::invalid_argument;
@@ -260,7 +260,7 @@
       socket_base::message_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_write(impl.socket_, impl.state_, ec);
+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
 
     return 0;
   }
@@ -326,7 +326,7 @@
       socket_base::message_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, impl.state_, ec);
+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
 
     return 0;
   }
@@ -395,7 +395,7 @@
       socket_base::message_flags& out_flags, asio::error_code& ec)
   {
     // Wait for socket to become ready.
-    socket_ops::poll_read(impl.socket_, impl.state_, ec);
+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
 
     // Clear out_flags, since we cannot give it any other sensible value when
     // performing a null_buffers operation.
diff --git a/asio/src/tests/unit/ip/tcp.cpp b/asio/src/tests/unit/ip/tcp.cpp
index 28e9a1f..8217d05 100644
--- a/asio/src/tests/unit/ip/tcp.cpp
+++ b/asio/src/tests/unit/ip/tcp.cpp
@@ -1269,7 +1269,90 @@
   }
 }
 
-} // namespace ip_tcp_resolver_compile
+} // namespace ip_tcp_resolver_entry_compile
+
+//------------------------------------------------------------------------------
+
+// ip_tcp_iostream_compile test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks that all public types and member functions on the
+// class ip::tcp::iostream compile and link correctly. Runtime failures are
+// ignored.
+
+namespace ip_tcp_iostream_compile {
+
+void test()
+{
+#if !defined(ASIO_NO_IOSTREAM)
+  using namespace asio;
+  namespace ip = asio::ip;
+
+  asio::io_context ioc;
+  asio::ip::tcp::socket sock(ioc);
+
+  // basic_socket_iostream typedefs.
+
+  (void)static_cast<ip::tcp::iostream::protocol_type*>(0);
+  (void)static_cast<ip::tcp::iostream::endpoint_type*>(0);
+  (void)static_cast<ip::tcp::iostream::clock_type*>(0);
+  (void)static_cast<ip::tcp::iostream::time_point*>(0);
+  (void)static_cast<ip::tcp::iostream::duration*>(0);
+  (void)static_cast<ip::tcp::iostream::traits_type*>(0);
+
+  // basic_socket_iostream constructors.
+
+  ip::tcp::iostream ios1;
+
+#if defined(ASIO_HAS_MOVE)
+  ip::tcp::iostream ios2(std::move(sock));
+#endif // defined(ASIO_HAS_MOVE)
+
+  ip::tcp::iostream ios3("hostname", "service");
+
+  // basic_socket_iostream operators.
+
+#if defined(ASIO_HAS_MOVE)
+  ios1 = ip::tcp::iostream();
+
+  ios2 = std::move(ios1);
+#endif // defined(ASIO_HAS_MOVE)
+
+  // basic_socket_iostream members.
+
+  ios1.connect("hostname", "service");
+
+  ios1.close();
+
+  (void)static_cast<std::streambuf*>(ios1.rdbuf());
+
+#if defined(ASIO_ENABLE_OLD_SERVICES)
+  basic_socket<ip::tcp, stream_socket_service<ip::tcp> >& sref = ios1.socket();
+#else // defined(ASIO_ENABLE_OLD_SERVICES)
+  basic_socket<ip::tcp>& sref = ios1.socket();
+#endif // defined(ASIO_ENABLE_OLD_SERVICES)
+  (void)sref;
+
+  error_code ec = ios1.error();
+  (void)ec;
+
+  ip::tcp::iostream::time_point tp = ios1.expiry();
+  (void)tp;
+
+  ios1.expires_at(tp);
+
+  ip::tcp::iostream::duration d;
+  ios1.expires_after(d);
+
+  // iostream operators.
+
+  int i = 0;
+  ios1 >> i;
+  ios1 << i;
+#endif // !defined(ASIO_NO_IOSTREAM)
+}
+
+} // namespace ip_tcp_iostream_compile
+
 //------------------------------------------------------------------------------
 
 ASIO_TEST_SUITE
@@ -1283,4 +1366,6 @@
   ASIO_TEST_CASE(ip_tcp_acceptor_runtime::test)
   ASIO_TEST_CASE(ip_tcp_resolver_compile::test)
   ASIO_TEST_CASE(ip_tcp_resolver_entry_compile::test)
+  ASIO_TEST_CASE(ip_tcp_resolver_entry_compile::test)
+  ASIO_COMPILE_TEST_CASE(ip_tcp_iostream_compile::test)
 )