diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,13 @@
+# Version 0.5.1.0
+
+* Re-export `Network.Socket.withSocketsDo`.
+
+* Use TCP `send` and `recv` as eported by network-simple-0.2.1.0.
+
+
 # Version 0.5.0.0
 
- * Removed `Control.Proxy.TCP.Sync` and `Control.Proxy.TCP.Safe.Sync`.
+* Removed `Control.Proxy.TCP.Sync` and `Control.Proxy.TCP.Safe.Sync`.
 
 
 # Version 0.4.0.1
diff --git a/pipes-network.cabal b/pipes-network.cabal
--- a/pipes-network.cabal
+++ b/pipes-network.cabal
@@ -1,5 +1,5 @@
 name:               pipes-network
-version:            0.5.0.0
+version:            0.5.1.0
 license:            BSD3
 license-file:       LICENSE
 copyright:          Copyright (c) Renzo Carbonara 2012-2013, Paolo Capriotti 2012-2012.
@@ -19,13 +19,13 @@
   .
   This package is organized using the following namespaces:
   .
-  * "Control.Proxy.TCP" exports @pipes@ proxies and functions to deal with TCP
-  connections. Such proxies don't acquire nor release new resources within a
-  proxy pipeline.
+  * "Control.Proxy.TCP" exports 'Control.Proxy.Proxy's and functions for
+  establishing and using TCP connections.
   .
-  * "Control.Proxy.TCP.Safe" exports @pipes-safe@ proxies and functions to deal
-  with TCP connections. Such proxies may safely acquire and release resources
-  within a pipeline, using the facilities provided by the @pipes-safe@ package.
+  * "Control.Proxy.TCP.Safe" is similar to "Control.Proxy.TCP", except
+  the exported 'Control.Proxy.Proxy's themselves can obtain new network
+  resources safely by using the facilities providied by the @pipes-safe@
+  package.
   .
   See the @NEWS@ file in the source distribution to learn about any
   important changes between version.
@@ -40,15 +40,13 @@
         base           (==4.*),
         bytestring     (>=0.9.2.1),
         network,
-        network-simple (>=0.2.0.1 && <0.3),
+        network-simple (>=0.2.1 && <0.3),
         pipes          (>=3.2 && <3.4),
         pipes-safe     (>=1.1 && <1.3),
         transformers   (>=0.2 && <0.4)
     exposed-modules:
         Control.Proxy.TCP
         Control.Proxy.TCP.Safe
-    other-modules:
-        Control.Proxy.Network.Internal
     ghc-options: -Wall -fno-warn-unused-do-bind
 
 test-suite simple
diff --git a/src/Control/Proxy/Network/Internal.hs b/src/Control/Proxy/Network/Internal.hs
deleted file mode 100644
--- a/src/Control/Proxy/Network/Internal.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# OPTIONS_HADDOCK hide #-}
-
--- | This module doesn't belong to this namespace, but really, I don't
--- know where it belongs. Suggestions welcome.
---
--- There's a @data-timeout@ package, maybe we should depend on that.
-
-module Control.Proxy.Network.Internal (
-    Timeout(..)
-  , recv
-  , send
-  ) where
-
-import qualified Data.ByteString               as B
-import qualified Control.Exception             as E
-import           Data.Typeable                 (Typeable)
-import qualified Network.Socket                as NS
-import qualified Network.Socket.ByteString
-
-
--- |Exception thrown when a timeout has elapsed.
-data Timeout
-  = Timeout String -- ^Timeouted with an additional explanatory message.
-  deriving (Eq, Show, Typeable)
-
-instance E.Exception Timeout where
-
-
---------------------------------------------------------------------------------
-
--- | Read up to a limited number of bytes from a socket.
---
--- Returns `Nothing` if the remote end closed the connection or EOF was reached.
-recv :: NS.Socket -> Int -> IO (Maybe B.ByteString)
-recv sock nbytes = do
-     bs <- Network.Socket.ByteString.recv sock nbytes
-     if B.null bs
-        then return Nothing
-        else return (Just bs)
-{-# INLINE recv #-}
-
--- | Writes the given bytes to the socket.
-send :: NS.Socket -> B.ByteString -> IO ()
-send = Network.Socket.ByteString.sendAll
-{-# INLINE send #-}
diff --git a/src/Control/Proxy/TCP.hs b/src/Control/Proxy/TCP.hs
--- a/src/Control/Proxy/TCP.hs
+++ b/src/Control/Proxy/TCP.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+
 -- | This module exports functions that allow you to safely use 'NS.Socket'
 -- resources acquired and released outside a 'P.Proxy' pipeline.
 --
@@ -35,32 +37,67 @@
   , nsocketReadTimeoutS
   , socketWriteTimeoutD
 
-  -- * Exports
+  -- * Note to Windows users
+  -- $windows-users
+  , NS.withSocketsDo
+
+  -- * Types
   , S.HostPreference(..)
   , Timeout(..)
   ) where
 
+import qualified Control.Exception              as E
 import           Control.Monad.Trans.Class
 import qualified Control.Proxy                  as P
 import qualified Control.Proxy.Trans.Either     as PE
-import           Control.Proxy.Network.Internal
 import qualified Data.ByteString                as B
+import           Data.Data                      (Data,Typeable)
 import           Data.Monoid
 import qualified Network.Socket                 as NS
 import qualified Network.Simple.TCP             as S
 import           System.Timeout                 (timeout)
 
+
 --------------------------------------------------------------------------------
 
+-- $windows-users
+--
+-- If you are running Windows, then you /must/ call 'NS.withSocketsDo', just
+-- once, right at the beginning of your program. That is, change your program's
+-- 'main' function from:
+--
+-- @
+-- main = do
+--   print \"Hello world\"
+--   -- rest of the program...
+-- @
+--
+-- To:
+--
+-- @
+-- main = 'NS.withSocketsDo' $ do
+--   print \"Hello world\"
+--   -- rest of the program...
+-- @
+--
+-- If you don't do this, your networking code won't work and you will get many
+-- unexpected errors at runtime. If you use an operating system other than
+-- Windows then you don't need to do this, but it is harmless to do it, so it's
+-- recommended that you do for portability reasons.
+
+--------------------------------------------------------------------------------
+
 -- $client-side
 --
 -- Here's how you could run a TCP client:
 --
--- > connect "www.example.org" "80" $ \(connectionSocket, remoteAddr) -> do
--- >   putStrLn $ "Connection established to " ++ show remoteAddr
--- >   -- now you may use connectionSocket as you please within this scope.
--- >   -- possibly with any of the socketReadS, nsocketReadS or socketWriteD
--- >   -- proxies explained below.
+-- @
+-- 'S.connect' \"www.example.org\" \"80\" $ \(connectionSocket, remoteAddr) -> do
+--   putStrLn $ \"Connection established to \" ++ show remoteAddr
+--   -- Now you may use connectionSocket as you please within this scope,
+--   -- possibly using 'socketReadS', 'socketWriteD' or similar proxies
+--   -- explained below.
+-- @
 
 --------------------------------------------------------------------------------
 
@@ -69,11 +106,13 @@
 -- Here's how you can run a TCP server that handles in different threads each
 -- incoming connection to port @8000@ at IPv4 address @127.0.0.1@:
 --
--- > serve (Host "127.0.0.1") "8000" $ \(connectionSocket, remoteAddr) -> do
--- >   putStrLn $ "TCP connection established from " ++ show remoteAddr
--- >   -- now you may use connectionSocket as you please within this scope.
--- >   -- possibly with any of the socketReadS, nsocketReadS or socketWriteD
--- >   -- proxies explained below.
+-- @
+-- 'S.serve' ('S.Host' \"127.0.0.1\") \"8000\" $ \(connectionSocket, remoteAddr) -> do
+--   putStrLn $ \"TCP connection established from \" ++ show remoteAddr
+--   -- Now you may use connectionSocket as you please within this scope,
+--   -- possibly using 'socketReadS', 'socketWriteD' or similar proxies
+--   -- explained below.
+-- @
 --
 -- If you need more control on the way your server runs, then you can use more
 -- advanced functions such as 'listen', 'accept' and 'acceptFork'.
@@ -101,7 +140,7 @@
   -> () -> P.Producer p B.ByteString IO ()
 socketReadS nbytes sock () = P.runIdentityP loop where
     loop = do
-      mbs <- lift (recv sock nbytes)
+      mbs <- lift (S.recv sock nbytes)
       case mbs of
         Just bs -> P.respond bs >> loop
         Nothing -> return ()
@@ -115,7 +154,7 @@
   -> Int -> P.Server p Int B.ByteString IO ()
 nsocketReadS sock = P.runIdentityK loop where
     loop nbytes = do
-      mbs <- lift (recv sock nbytes)
+      mbs <- lift (S.recv sock nbytes)
       case mbs of
         Just bs -> P.respond bs >>= loop
         Nothing -> return ()
@@ -132,7 +171,7 @@
 socketWriteD sock = P.runIdentityK loop where
     loop x = do
       a <- P.request x
-      lift (send sock a)
+      lift (S.send sock a)
       P.respond a >>= loop
 {-# INLINABLE socketWriteD #-}
 
@@ -157,7 +196,7 @@
   -> () -> P.Producer (PE.EitherP Timeout p) B.ByteString IO ()
 socketReadTimeoutS wait nbytes sock () = loop where
     loop = do
-      mmbs <- lift (timeout wait (recv sock nbytes))
+      mmbs <- lift (timeout wait (S.recv sock nbytes))
       case mmbs of
         Just (Just bs) -> P.respond bs >> loop
         Just Nothing   -> return ()
@@ -175,7 +214,7 @@
   -> Int -> P.Server (PE.EitherP Timeout p) Int B.ByteString IO ()
 nsocketReadTimeoutS wait sock = loop where
     loop nbytes = do
-      mmbs <- lift (timeout wait (recv sock nbytes))
+      mmbs <- lift (timeout wait (S.recv sock nbytes))
       case mmbs of
         Just (Just bs) -> P.respond bs >>= loop
         Just Nothing   -> return ()
@@ -194,11 +233,18 @@
 socketWriteTimeoutD wait sock = loop where
     loop x = do
       a <- P.request x
-      m <- lift (timeout wait (send sock a))
+      m <- lift (timeout wait (S.send sock a))
       case m of
         Just () -> P.respond a >>= loop
         Nothing -> PE.throw ex
     ex = Timeout $ "socketWriteTimeoutD: " <> show wait <> " microseconds."
 {-# INLINABLE socketWriteTimeoutD #-}
 
+--------------------------------------------------------------------------------
 
+-- |Exception thrown when a time limit has elapsed.
+data Timeout
+  = Timeout String -- ^Timeouted with an additional explanatory message.
+  deriving (Eq, Show, Data, Typeable)
+
+instance E.Exception Timeout where
diff --git a/src/Control/Proxy/TCP/Safe.hs b/src/Control/Proxy/TCP/Safe.hs
--- a/src/Control/Proxy/TCP/Safe.hs
+++ b/src/Control/Proxy/TCP/Safe.hs
@@ -37,6 +37,11 @@
   nsocketReadS,
   socketWriteD,
 
+  -- * Note to Windows users
+  -- $windows-users
+  NS.withSocketsDo,
+
+
   -- * Exports
   S.HostPreference(..),
   Timeout(..)
@@ -45,8 +50,8 @@
 import           Control.Concurrent             (ThreadId)
 import           Control.Monad
 import qualified Control.Proxy                  as P
-import           Control.Proxy.Network.Internal
 import qualified Control.Proxy.Safe             as P
+import           Control.Proxy.TCP              (Timeout(..))
 import qualified Data.ByteString                as B
 import           Data.Monoid
 import qualified Network.Socket                 as NS
@@ -55,15 +60,44 @@
 
 --------------------------------------------------------------------------------
 
+-- $windows-users
+--
+-- If you are running Windows, then you /must/ call 'NS.withSocketsDo', just
+-- once, right at the beginning of your program. That is, change your program's
+-- 'main' function from:
+--
+-- @
+-- main = do
+--   print \"Hello world\"
+--   -- rest of the program...
+-- @
+--
+-- To:
+--
+-- @
+-- main = 'NS.withSocketsDo' $ do
+--   print \"Hello world\"
+--   -- rest of the program...
+-- @
+--
+-- If you don't do this, your networking code won't work and you will get many
+-- unexpected errors at runtime. If you use an operating system other than
+-- Windows then you don't need to do this, but it is harmless to do it, so it's
+-- recommended that you do for portability reasons.
+
+--------------------------------------------------------------------------------
+
 -- $client-side
 --
 -- Here's how you could run a TCP client:
 --
--- > connect "www.example.org" "80" $ \(connectionSocket, remoteAddr) -> do
--- >   tryIO . putStrLn $ "Connection established to " ++ show remoteAddr
--- >   -- now you may use connectionSocket as you please within this scope.
--- >   -- possibly with any of the socketReadS, nsocketReadS or socketWriteD
--- >   -- proxies explained below.
+-- @
+-- 'connect' \"www.example.org\" \"80\" $ \(connectionSocket, remoteAddr) -> do
+--   putStrLn $ \"Connection established to \" ++ show remoteAddr
+--   -- Now you may use connectionSocket as you please within this scope,
+--   -- possibly using 'socketReadS', 'socketWriteD' or similar proxies
+--   -- explained below.
+-- @
 --
 -- You might instead prefer the simpler but less general solutions offered by
 -- 'connectReadS' and 'connectWriteD', so check those too.
@@ -160,11 +194,13 @@
 -- Here's how you can run a TCP server that handles in different threads each
 -- incoming connection to port @8000@ at IPv4 address @127.0.0.1@:
 --
--- > serve (Host "127.0.0.1") "8000" $ \(connectionSocket, remoteAddr) -> do
--- >   tryIO . putStrLn $ "TCP connection established from " ++ show remoteAddr
--- >   -- now you may use connectionSocket as you please within this scope.
--- >   -- possibly with any of the socketReadS, nsocketReadS or socketWriteD
--- >   -- proxies explained below.
+-- @
+-- 'serve' ('Host' \"127.0.0.1\") \"8000\" $ \(connectionSocket, remoteAddr) -> do
+--   putStrLn $ \"TCP connection established from \" ++ show remoteAddr
+--   -- Now you may use connectionSocket as you please within this scope,
+--   -- possibly using 'socketReadS', 'socketWriteD' or similar proxies
+--   -- explained below.
+-- @
 --
 -- You might instead prefer the simpler but less general solutions offered by
 -- 'serveReadS' and 'serveWriteD', so check those too. On the other hand,
@@ -364,13 +400,13 @@
   -> () -> P.Producer (P.ExceptionP p) B.ByteString P.SafeIO ()
 socketReadS Nothing nbytes sock () = loop where
     loop = do
-      mbs <- P.tryIO (recv sock nbytes)
+      mbs <- P.tryIO (S.recv sock nbytes)
       case mbs of
         Just bs -> P.respond bs >> loop
         Nothing -> return ()
 socketReadS (Just wait) nbytes sock () = loop where
     loop = do
-      mmbs <- P.tryIO (timeout wait (recv sock nbytes))
+      mmbs <- P.tryIO (timeout wait (S.recv sock nbytes))
       case mmbs of
         Just (Just bs) -> P.respond bs >> loop
         Just Nothing   -> return ()
@@ -387,13 +423,13 @@
   -> Int -> P.Server (P.ExceptionP p) Int B.ByteString P.SafeIO ()
 nsocketReadS Nothing sock = loop where
     loop nbytes = do
-      mbs <- P.tryIO (recv sock nbytes)
+      mbs <- P.tryIO (S.recv sock nbytes)
       case mbs of
         Just bs -> P.respond bs >>= loop
         Nothing -> return ()
 nsocketReadS (Just wait) sock = loop where
     loop nbytes = do
-      mbs <- P.tryIO (timeout wait (recv sock nbytes))
+      mbs <- P.tryIO (timeout wait (S.recv sock nbytes))
       case mbs of
         Just (Just bs) -> P.respond bs >>= loop
         Just Nothing   -> return ()
@@ -417,12 +453,12 @@
 socketWriteD Nothing sock = loop where
     loop x = do
       a <- P.request x
-      P.tryIO (send sock a)
+      P.tryIO (S.send sock a)
       P.respond a >>= loop
 socketWriteD (Just wait) sock = loop where
     loop x = do
       a <- P.request x
-      m <- P.tryIO (timeout wait (send sock a))
+      m <- P.tryIO (timeout wait (S.send sock a))
       case m of
         Just () -> P.respond a >>= loop
         Nothing -> P.throw ex
