Sync mio TCP and libstd TCP APIs

* Rename `take_socket_error` to `take_error`, tweak return type.
* Add `property` accessors in addition to `set_property`
* Rename `set_keepalive` to `set_keepalive_ms` to make room for `Duration` later
  on.

Closes #458
diff --git a/.travis.yml b/.travis.yml
index d69ad85..3c7cbd9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@
   - stable
   # The following Rust version represents the oldest supported version of Mio.
   # This value should not be changed without prior discussion.
-  - 1.8.0
+  - 1.9.0
 
 os:
   - linux
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1312c46..94e6357 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
 * Shift primary API towards `Poll`
 * `EventLoop` and types to `deprecated` mod. All contents of the
   `deprecated` mod will be removed by Mio 1.0.
-* Increase minimum supported Rust version to 1.8.0
+* Increase minimum supported Rust version to 1.9.0
 * Deprecate unix domain socket implementation in favor of using a
   version external to Mio. For example: https://github.com/alexcrichton/mio-uds.
 * Remove various types now included in `std`
diff --git a/Cargo.toml b/Cargo.toml
index 3d02f64..d28c746 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,7 +21,7 @@
 lazycell = "0.4.0"
 log      = "0.3.1"
 slab     = "0.3.0"
-net2     = { version = "0.2.19", default-features = false }
+net2     = "0.2.19"
 
 [target.'cfg(unix)'.dependencies]
 nix    = "0.6.0"
diff --git a/src/net/tcp.rs b/src/net/tcp.rs
index 672747d..90b9dc3 100644
--- a/src/net/tcp.rs
+++ b/src/net/tcp.rs
@@ -71,14 +71,22 @@
         })
     }
 
+    /// Returns the socket address of the remote peer of this TCP connection.
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         self.sys.peer_addr()
     }
 
+    /// Returns the socket address of the local half of this TCP connection.
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
         self.sys.local_addr()
     }
 
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `TcpStream` is a reference to the same stream that this
+    /// object references. Both handles will read and write the same stream of
+    /// data, and options set on one stream will be propagated to the other
+    /// stream.
     pub fn try_clone(&self) -> io::Result<TcpStream> {
         self.sys.try_clone().map(|s| {
             TcpStream {
@@ -87,20 +95,86 @@
             }
         })
     }
+
+    /// Shuts down the read, write, or both halves of this connection.
+    ///
+    /// This function will cause all pending and future I/O on the specified
+    /// portions to return immediately with an appropriate value (see the
+    /// documentation of `Shutdown`).
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         self.sys.shutdown(how)
     }
 
+    /// Sets the value of the `TCP_NODELAY` option on this socket.
+    ///
+    /// If set, this option disables the Nagle algorithm. This means that
+    /// segments are always sent as soon as possible, even if there is only a
+    /// small amount of data. When not set, data is buffered until there is a
+    /// sufficient amount to send out, thereby avoiding the frequent sending of
+    /// small packets.
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         self.sys.set_nodelay(nodelay)
     }
 
-    pub fn set_keepalive(&self, seconds: Option<u32>) -> io::Result<()> {
-        self.sys.set_keepalive(seconds)
+    /// Gets the value of the `TCP_NODELAY` option on this socket.
+    ///
+    /// For more information about this option, see [`set_nodelay`][link].
+    ///
+    /// [link]: #method.set_nodelay
+    pub fn nodelay(&self) -> io::Result<bool> {
+        self.sys.nodelay()
     }
 
-    pub fn take_socket_error(&self) -> io::Result<()> {
-        self.sys.take_socket_error()
+    /// Sets whether keepalive messages are enabled to be sent on this socket.
+    ///
+    /// On Unix, this option will set the `SO_KEEPALIVE` as well as the
+    /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
+    /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
+    ///
+    /// If `None` is specified then keepalive messages are disabled, otherwise
+    /// the number of milliseconds specified will be the time to remain idle
+    /// before sending a TCP keepalive probe.
+    ///
+    /// Some platforms specify this value in seconds, so sub-second millisecond
+    /// specifications may be omitted.
+    pub fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
+        self.sys.set_keepalive_ms(keepalive)
+    }
+
+    /// Returns whether keepalive messages are enabled on this socket, and if so
+    /// the amount of milliseconds between them.
+    ///
+    /// For more information about this option, see [`set_keepalive_ms`][link].
+    ///
+    /// [link]: #method.set_keepalive_ms
+    pub fn keepalive_ms(&self) -> io::Result<Option<u32>> {
+        self.sys.keepalive_ms()
+    }
+
+    /// Sets the value for the `IP_TTL` option on this socket.
+    ///
+    /// This value sets the time-to-live field that is used in every packet sent
+    /// from this socket.
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        self.sys.set_ttl(ttl)
+    }
+
+    /// Gets the value of the `IP_TTL` option for this socket.
+    ///
+    /// For more information about this option, see [`set_ttl`][link].
+    ///
+    /// [link]: #method.set_ttl
+    pub fn ttl(&self) -> io::Result<u32> {
+        self.sys.ttl()
+    }
+
+    /// Get the value of the `SO_ERROR` option on this socket.
+    ///
+    /// This will retrieve the stored error in the underlying socket, clearing
+    /// the field in the process. This can be useful for checking errors between
+    /// calls.
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.sys.take_error()
     }
 }
 
@@ -253,10 +327,16 @@
         })
     }
 
+    /// Returns the local socket address of this listener.
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
         self.sys.local_addr()
     }
 
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `TcpListener` is a reference to the same socket that this
+    /// object references. Both handles can be used to accept incoming
+    /// connections and options set on one listener will affect the other.
     pub fn try_clone(&self) -> io::Result<TcpListener> {
         self.sys.try_clone().map(|s| {
             TcpListener {
@@ -266,8 +346,51 @@
         })
     }
 
-    pub fn take_socket_error(&self) -> io::Result<()> {
-        self.sys.take_socket_error()
+    /// Sets the value for the `IP_TTL` option on this socket.
+    ///
+    /// This value sets the time-to-live field that is used in every packet sent
+    /// from this socket.
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        self.sys.set_ttl(ttl)
+    }
+
+    /// Gets the value of the `IP_TTL` option for this socket.
+    ///
+    /// For more information about this option, see [`set_ttl`][link].
+    ///
+    /// [link]: #method.set_ttl
+    pub fn ttl(&self) -> io::Result<u32> {
+        self.sys.ttl()
+    }
+
+    /// Sets the value for the `IPV6_V6ONLY` option on this socket.
+    ///
+    /// If this is set to `true` then the socket is restricted to sending and
+    /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
+    /// can bind the same port at the same time.
+    ///
+    /// If this is set to `false` then the socket can be used to send and
+    /// receive packets from an IPv4-mapped IPv6 address.
+    pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
+        self.sys.set_only_v6(only_v6)
+    }
+
+    /// Gets the value of the `IPV6_V6ONLY` option for this socket.
+    ///
+    /// For more information about this option, see [`set_only_v6`][link].
+    ///
+    /// [link]: #method.set_only_v6
+    pub fn only_v6(&self) -> io::Result<bool> {
+        self.sys.only_v6()
+    }
+
+    /// Get the value of the `SO_ERROR` option on this socket.
+    ///
+    /// This will retrieve the stored error in the underlying socket, clearing
+    /// the field in the process. This can be useful for checking errors between
+    /// calls.
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.sys.take_error()
     }
 }
 
diff --git a/src/sys/unix/tcp.rs b/src/sys/unix/tcp.rs
index ccac224..b9505b8 100644
--- a/src/sys/unix/tcp.rs
+++ b/src/sys/unix/tcp.rs
@@ -5,9 +5,6 @@
 use libc;
 use net2::TcpStreamExt;
 
-#[allow(unused_imports)]
-use net2::TcpListenerExt;
-
 use {io, Evented, Ready, Poll, PollOpt, Token};
 
 use sys::unix::eventedfd::EventedFd;
@@ -59,20 +56,31 @@
     }
 
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
-        TcpStreamExt::set_nodelay(&self.inner, nodelay)
+        self.inner.set_nodelay(nodelay)
     }
 
-    pub fn set_keepalive(&self, seconds: Option<u32>) -> io::Result<()> {
-        self.inner.set_keepalive_ms(seconds.map(|s| s * 1000))
+    pub fn nodelay(&self) -> io::Result<bool> {
+        self.inner.nodelay()
     }
 
-    pub fn take_socket_error(&self) -> io::Result<()> {
-        self.inner.take_error().and_then(|e| {
-            match e {
-                Some(e) => Err(e),
-                None => Ok(())
-            }
-        })
+    pub fn set_keepalive_ms(&self, millis: Option<u32>) -> io::Result<()> {
+        self.inner.set_keepalive_ms(millis)
+    }
+
+    pub fn keepalive_ms(&self) -> io::Result<Option<u32>> {
+        self.inner.keepalive_ms()
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        self.inner.set_ttl(ttl)
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        self.inner.ttl()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.inner.take_error()
     }
 }
 
@@ -157,13 +165,24 @@
         })
     }
 
-    pub fn take_socket_error(&self) -> io::Result<()> {
-        self.inner.take_error().and_then(|e| {
-            match e {
-                Some(e) => Err(e),
-                None => Ok(())
-            }
-        })
+    pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
+        self.inner.set_only_v6(only_v6)
+    }
+
+    pub fn only_v6(&self) -> io::Result<bool> {
+        self.inner.only_v6()
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        self.inner.set_ttl(ttl)
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        self.inner.ttl()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.inner.take_error()
     }
 }
 
diff --git a/src/sys/windows/tcp.rs b/src/sys/windows/tcp.rs
index a30aea9..32c73f0 100644
--- a/src/sys/windows/tcp.rs
+++ b/src/sys/windows/tcp.rs
@@ -7,7 +7,7 @@
 use io::would_block;
 use miow::iocp::CompletionStatus;
 use miow::net::*;
-use net2::{self, TcpBuilder};
+use net2::{TcpBuilder, TcpStreamExt as Net2TcpExt};
 use net::tcp::Shutdown;
 use winapi::*;
 
@@ -129,21 +129,31 @@
     }
 
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
-        net2::TcpStreamExt::set_nodelay(&self.imp.inner.socket, nodelay)
+        self.imp.inner.socket.set_nodelay(nodelay)
     }
 
-    pub fn set_keepalive(&self, seconds: Option<u32>) -> io::Result<()> {
-        let dur = seconds.map(|s| s * 1000);
-        net2::TcpStreamExt::set_keepalive_ms(&self.imp.inner.socket, dur)
+    pub fn nodelay(&self) -> io::Result<bool> {
+        self.imp.inner.socket.nodelay()
     }
 
-    pub fn take_socket_error(&self) -> io::Result<()> {
-        net2::TcpStreamExt::take_error(&self.imp.inner.socket).and_then(|e| {
-            match e {
-                Some(e) => Err(e),
-                None => Ok(())
-            }
-        })
+    pub fn set_keepalive_ms(&self, millis: Option<u32>) -> io::Result<()> {
+        self.imp.inner.socket.set_keepalive_ms(millis)
+    }
+
+    pub fn keepalive_ms(&self) -> io::Result<Option<u32>> {
+        self.imp.inner.socket.keepalive_ms()
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        self.imp.inner.socket.set_ttl(ttl)
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        self.imp.inner.socket.ttl()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.imp.inner.socket.take_error()
     }
 
     fn inner(&self) -> MutexGuard<StreamInner> {
@@ -507,13 +517,24 @@
         })
     }
 
-    pub fn take_socket_error(&self) -> io::Result<()> {
-        net2::TcpListenerExt::take_error(&self.imp.inner.socket).and_then(|e| {
-            match e {
-                Some(e) => Err(e),
-                None => Ok(())
-            }
-        })
+    pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
+        self.imp.inner.socket.set_only_v6(only_v6)
+    }
+
+    pub fn only_v6(&self) -> io::Result<bool> {
+        self.imp.inner.socket.only_v6()
+    }
+
+    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+        self.imp.inner.socket.set_ttl(ttl)
+    }
+
+    pub fn ttl(&self) -> io::Result<u32> {
+        self.imp.inner.socket.ttl()
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.imp.inner.socket.take_error()
     }
 
     fn inner(&self) -> MutexGuard<ListenerInner> {