diff --git a/PEOPLE b/PEOPLE
--- a/PEOPLE
+++ b/PEOPLE
@@ -1,9 +1,11 @@
 The following people have participated in creating this library, either
-by directly contributing code or by providing thoughtful input in
-discussions about the library design.
+by directly contributing code, by providing thoughtful input in
+discussions about the library design, or by doing anything else that
+helps this library move forwards.
 
 Renzo Carbonara
 Gabriel Gonzalez
 Paolo Capriotti
 Marius Ghita
 Kyle Van Berendonck
+Nicolas Trangez
diff --git a/changelog b/changelog
deleted file mode 100644
--- a/changelog
+++ /dev/null
@@ -1,94 +0,0 @@
-# Version 0.6.3
-
-* Bump `network-simple`, `transformers` and `pipes-safe` upper bounds.
-
-* Remove `Base m ~ IO` constraints from `Pipes.Network.TCP.Safe`, as
-  not all of them were removed in 0.6.1.
-
-
-# Version 0.6.2
-
-* Dependency bumps (upper bounds).
-
-
-# Version 0.6.1
-
-* Remove the `Base m ~ IO` constraint from `Pipes.Network.TCP.Safe`
-
-
-# Version 0.6.0
-
-* Significantly upgraded the API and renamed functions to play well with
-  pipes-4.0.0, pipes-safe-2.0.0 and network-simple-0.3.0.
-
-* Throw `IOError` in `IO` in order to report timeout errors. Delete
-  the `Timeout` data-type.
-
-
-# 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`.
-
-
-# Version 0.4.0.1
-
-* FIX: `acceptFork` now properly closes the connection socket, even in
-  case of asynchronous exceptions.
-
-
-# Version 0.4.0.0
-
-* Do not handle “Broken Pipe” errors on the `*Write*D` proxies anymore.
-  As as a result, those proxies run forever and have a polymorphic
-  return value, which makes this release binary compatible with 0.2.0.0,
-  but not with 0.3.0.0.
-
-
-# Version 0.3.0.0
-
-* Quietly stop writing or reading bytes from a TCP socket if a
-  “Broken Pipe” error happens, indicating that the remote end
-  already closed the connection. Previously, a `ResourceVanished`
-  exception was thrown.
-
-* All the `*Write*D` proxies now return `()` if the remote end
-  closed the connection.
-
-
-# Version 0.2.0.0
-
-* Depend on network-simple 0.2
-
-* In both modules `Control.Proxy.TCP` and `Control.Proxy.TCP.Safe`:
-  `serveFork` was renamed to `serve` and the previous function named
-  `serve` was removed.
-
-
-# Version 0.1.1.0
-
-* Split many of the non-pipes-related TCP utilities to the own
-  `network-simple` package.
-* Depend on `network-simple` and re-export its functions.
-
-
-# Version 0.1.0.1
-
-* Dependency bumps.
-
-
-# Version 0.1.0
-
-* New backwards incompatible API
-* Based on pipes 3.1
-
-
-# Up to version 0.0.2
-
-* Based on pipes-core.
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,108 @@
+# Version 0.6.4
+
+* The various `fromServe` and `toServe*` pipes from
+  `Pipes.Network.TCP.Safe` now close the listening socket immediately
+  after accepting a first connection.
+
+* Re-export `sendLazy`, `sendMany` and `closeSock`.
+
+* Add `to{Socket,SocketTimeout,Serve,Connect}{Lazy,Many}`.
+
+* Fix issue #29 where `fromSocketTimeout` and `fromSocketTimeoutN`
+  would loop forever.
+
+
+# Version 0.6.3
+
+* Bump `network-simple`, `transformers` and `pipes-safe` upper bounds.
+
+* Remove `Base m ~ IO` constraints from `Pipes.Network.TCP.Safe`, as
+  not all of them were removed in 0.6.1.
+
+
+# Version 0.6.2
+
+* Dependency bumps (upper bounds).
+
+
+# Version 0.6.1
+
+* Remove the `Base m ~ IO` constraint from `Pipes.Network.TCP.Safe`
+
+
+# Version 0.6.0
+
+* Significantly upgraded the API and renamed functions to play well with
+  pipes-4.0.0, pipes-safe-2.0.0 and network-simple-0.3.0.
+
+* Throw `IOError` in `IO` in order to report timeout errors. Delete
+  the `Timeout` data-type.
+
+
+# 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`.
+
+
+# Version 0.4.0.1
+
+* FIX: `acceptFork` now properly closes the connection socket, even in
+  case of asynchronous exceptions.
+
+
+# Version 0.4.0.0
+
+* Do not handle “Broken Pipe” errors on the `*Write*D` proxies anymore.
+  As as a result, those proxies run forever and have a polymorphic
+  return value, which makes this release binary compatible with 0.2.0.0,
+  but not with 0.3.0.0.
+
+
+# Version 0.3.0.0
+
+* Quietly stop writing or reading bytes from a TCP socket if a
+  “Broken Pipe” error happens, indicating that the remote end
+  already closed the connection. Previously, a `ResourceVanished`
+  exception was thrown.
+
+* All the `*Write*D` proxies now return `()` if the remote end
+  closed the connection.
+
+
+# Version 0.2.0.0
+
+* Depend on network-simple 0.2
+
+* In both modules `Control.Proxy.TCP` and `Control.Proxy.TCP.Safe`:
+  `serveFork` was renamed to `serve` and the previous function named
+  `serve` was removed.
+
+
+# Version 0.1.1.0
+
+* Split many of the non-pipes-related TCP utilities to the own
+  `network-simple` package.
+* Depend on `network-simple` and re-export its functions.
+
+
+# Version 0.1.0.1
+
+* Dependency bumps.
+
+
+# Version 0.1.0
+
+* New backwards incompatible API
+* Based on pipes 3.1
+
+
+# Up to version 0.0.2
+
+* Based on pipes-core.
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.6.3
+version:            0.6.4
 license:            BSD3
 license-file:       LICENSE
 copyright:          Copyright (c) Renzo Carbonara 2012-2014, Paolo Capriotti 2012-2012.
@@ -13,7 +13,7 @@
 build-type:         Simple
 synopsis:           Use network sockets together with the pipes library.
 cabal-version:      >=1.8
-extra-source-files: README.md PEOPLE changelog
+extra-source-files: README.md PEOPLE changelog.md
 description:
   Use network sockets together with the @pipes@ library.
   .
@@ -41,7 +41,7 @@
         base           (==4.*),
         bytestring     (>=0.9.2.1),
         network,
-        network-simple (>=0.3 && <0.5),
+        network-simple (>=0.4.0.1 && <0.5),
         pipes          (>=4.0 && <4.2),
         pipes-safe     (>=2.1 && <2.3),
         transformers   (>=0.2 && <0.5)
@@ -49,4 +49,3 @@
         Pipes.Network.TCP
         Pipes.Network.TCP.Safe
     ghc-options: -Wall -O2
-
diff --git a/src/Pipes/Network/TCP.hs b/src/Pipes/Network/TCP.hs
--- a/src/Pipes/Network/TCP.hs
+++ b/src/Pipes/Network/TCP.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE RankNTypes #-}
 
 -- | This minimal module exports facilities that ease the usage of TCP
+
 -- 'Socket's in the /Pipes ecosystem/. It is meant to be used together with
 -- the "Network.Simple.TCP" module from the @network-simple@ package, which is
 -- completely re-exported from this module.
@@ -24,19 +25,25 @@
   -- * Sending
   -- $sending
   , toSocket
+  , toSocketLazy
+  , toSocketMany
   , toSocketTimeout
+  , toSocketTimeoutLazy
+  , toSocketTimeoutMany
   -- * Exports
   -- $exports
   , module Network.Simple.TCP
   ) where
 
 import qualified Data.ByteString                as B
+import qualified Data.ByteString.Lazy           as BL
 import           Foreign.C.Error                (errnoToIOError, eTIMEDOUT)
 import qualified Network.Socket.ByteString      as NSB
 import           Network.Simple.TCP
                   (connect, serve, listen, accept, acceptFork,
-                   bindSock, connectSock, recv, send, withSocketsDo,
-                   HostName, HostPreference(HostAny, HostIPv4, HostIPv6, Host),
+                   bindSock, connectSock, closeSock, recv, send, sendLazy,
+                   sendMany, withSocketsDo, HostName,
+                   HostPreference(HostAny, HostIPv4, HostIPv6, Host),
                    ServiceName, SockAddr, Socket)
 import           Pipes
 import           Pipes.Core
@@ -46,13 +53,13 @@
 
 -- $receiving
 --
--- The following pipes allow you to receive bytes from the remote end.
+-- The following producers allow you to receive bytes from the remote end.
 --
--- Besides the pipes below, you might want to use "Network.Simple.TCP"'s
--- 'Network.Simple.TCP.recv', which happens to be an 'Effect'':
+-- Besides the producers below, you might want to use "Network.Simple.TCP"'s
+-- 'recv', which happens to be an 'Effect'':
 --
 -- @
--- 'Network.Simple.TCP.recv' :: 'MonadIO' m => 'Socket' -> 'Int' -> 'Effect'' m ('Maybe' 'B.ByteString')
+-- 'recv' :: 'MonadIO' m => 'Socket' -> 'Int' -> 'Effect'' m ('Maybe' 'B.ByteString')
 -- @
 
 --------------------------------------------------------------------------------
@@ -91,7 +98,9 @@
     loop = do
        mbs <- liftIO (timeout wait (NSB.recv sock nbytes))
        case mbs of
-          Just bs -> yield bs >> loop
+          Just bs
+           | B.null bs -> return ()
+           | otherwise -> yield bs >> loop
           Nothing -> liftIO $ ioError $ errnoToIOError
              "Pipes.Network.TCP.fromSocketTimeout" eTIMEDOUT Nothing Nothing
 {-# INLINABLE fromSocketTimeout #-}
@@ -129,7 +138,9 @@
     loop = \nbytes -> do
        mbs <- liftIO (timeout wait (NSB.recv sock nbytes))
        case mbs of
-          Just bs -> respond bs >>= loop
+          Just bs
+           | B.null bs -> return ()
+           | otherwise -> respond bs >>= loop
           Nothing -> liftIO $ ioError $ errnoToIOError
              "Pipes.Network.TCP.fromSocketTimeoutN" eTIMEDOUT Nothing Nothing
 {-# INLINABLE fromSocketTimeoutN #-}
@@ -138,13 +149,15 @@
 
 -- $sending
 --
--- The following pipes allow you to send bytes to the remote end.
+-- The following consumers allow you to send bytes to the remote end.
 --
--- Besides the pipes below, you might want to use "Network.Simple.TCP"'s
--- 'Network.Simple.TCP.send', which happens to be an 'Effect'':
+-- Besides the consumers below, you might want to use "Network.Simple.TCP"'s
+-- 'send', 'sendLazy' or 'sendMany' which happen to be 'Effect''s:
 --
 -- @
--- 'Network.Simple.TCP.send' :: 'MonadIO' m => 'Socket' -> 'B.ByteString' -> 'Effect'' m ()
+-- 'send'     :: 'MonadIO' m => 'Socket' ->  'B.ByteString'  -> 'Effect'' m ()
+-- 'sendLazy' :: 'MonadIO' m => 'Socket' ->  'BL.ByteString'  -> 'Effect'' m ()
+-- 'sendMany' :: 'MonadIO' m => 'Socket' -> ['B.ByteString'] -> 'Effect'' m ()
 -- @
 
 -- | Sends to the remote end each 'B.ByteString' received from upstream.
@@ -155,20 +168,64 @@
 toSocket sock = for cat (\a -> send sock a)
 {-# INLINABLE toSocket #-}
 
+-- | Like 'toSocket' but takes a lazy 'BL.ByteSring' and sends it in a more
+-- efficient manner (compared to converting it to a strict 'B.ByteString' and
+-- sending it).
+toSocketLazy
+  :: MonadIO m
+  => Socket  -- ^Connected socket.
+  -> Consumer' BL.ByteString m r
+toSocketLazy sock = for cat (\a -> sendLazy sock a)
+{-# INLINABLE toSocketLazy #-}
+
+-- | Like 'toSocket' but takes a @['BL.ByteSring']@ and sends it in a more
+-- efficient manner (compared to converting it to a strict 'B.ByteString' and
+-- sending it).
+toSocketMany
+  :: MonadIO m
+  => Socket  -- ^Connected socket.
+  -> Consumer' [B.ByteString] m r
+toSocketMany sock = for cat (\a -> sendMany sock a)
+{-# INLINABLE toSocketMany #-}
+
 -- | Like 'toSocket', except with the first 'Int' argument you can specify
 -- the maximum time that each interaction with the remote end can take. If such
 -- time elapses before the interaction finishes, then an 'IOError' exception is
 -- thrown. The time is specified in microseconds (1 second = 1e6 microseconds).
-toSocketTimeout
+toSocketTimeout :: MonadIO m => Int -> Socket -> Consumer' B.ByteString m r
+toSocketTimeout = _toSocketTimeout send "Pipes.Network.TCP.toSocketTimeout"
+{-# INLINABLE toSocketTimeout #-}
+
+-- | Like 'toSocketTimeout' but takes a lazy 'BL.ByteSring' and sends it in a
+-- more efficient manner (compared to converting it to a strict 'B.ByteString'
+-- and sending it).
+toSocketTimeoutLazy :: MonadIO m => Int -> Socket -> Consumer' BL.ByteString m r
+toSocketTimeoutLazy =
+    _toSocketTimeout sendLazy "Pipes.Network.TCP.toSocketTimeoutLazy"
+{-# INLINABLE toSocketTimeoutLazy #-}
+
+-- | Like 'toSocketTimeout' but takes a @['BL.ByteSring']@ and sends it in a
+-- more efficient manner (compared to converting it to a strict 'B.ByteString'
+-- and sending it).
+toSocketTimeoutMany
+  :: MonadIO m => Int -> Socket -> Consumer' [B.ByteString] m r
+toSocketTimeoutMany =
+    _toSocketTimeout sendMany "Pipes.Network.TCP.toSocketTimeoutMany"
+{-# INLINABLE toSocketTimeoutMany #-}
+
+_toSocketTimeout
   :: MonadIO m
-  => Int -> Socket -> Consumer' B.ByteString m r
-toSocketTimeout wait sock = for cat $ \a -> do
-    mu <- liftIO (timeout wait (NSB.sendAll sock a))
+  => (Socket -> a -> IO ())
+  -> String
+  -> Int
+  -> Socket
+  -> Consumer' a m r
+_toSocketTimeout send' nm = \wait sock -> for cat $ \a -> do
+    mu <- liftIO (timeout wait (send' sock a))
     case mu of
-       Just () -> return ()
-       Nothing -> liftIO $ ioError $ errnoToIOError
-          "Pipes.Network.TCP.toSocketTimeout" eTIMEDOUT Nothing Nothing
-{-# INLINABLE toSocketTimeout #-}
+      Just () -> return ()
+      Nothing -> liftIO $ ioError $ errnoToIOError nm eTIMEDOUT Nothing Nothing
+{-# INLINABLE _toSocketTimeout #-}
 
 --------------------------------------------------------------------------------
 
@@ -180,10 +237,13 @@
 --     'bindSock',
 --     'connect',
 --     'connectSock',
+--     'closeSock',
 --     'HostPreference'('HostAny','HostIPv4','HostIPv6','Host'),
 --     'listen',
 --     'recv',
 --     'send',
+--     'sendLazy',
+--     'sendMany',
 --     'serve'.
 --
 -- [From "Network.Socket"]
diff --git a/src/Pipes/Network/TCP/Safe.hs b/src/Pipes/Network/TCP/Safe.hs
--- a/src/Pipes/Network/TCP/Safe.hs
+++ b/src/Pipes/Network/TCP/Safe.hs
@@ -26,10 +26,14 @@
   -- $client-streaming
   , fromConnect
   , toConnect
+  , toConnectLazy
+  , toConnectMany
   -- ** Server side
   -- $server-streaming
   , fromServe
   , toServe
+  , toServeLazy
+  , toServeMany
   -- * Exports
   -- $exports
   , module Pipes.Network.TCP
@@ -39,15 +43,18 @@
 
 import           Control.Monad
 import qualified Data.ByteString        as B
+import qualified Data.ByteString.Lazy   as BL
 import           Network.Simple.TCP
-                  (acceptFork, bindSock, connectSock, recv, send, withSocketsDo,
-                   HostName, HostPreference(HostAny, HostIPv4, HostIPv6, Host),
+                  (acceptFork, bindSock, connectSock, closeSock, recv, send,
+                   sendLazy, sendMany, withSocketsDo, HostName,
+                   HostPreference(HostAny, HostIPv4, HostIPv6, Host),
                    ServiceName, SockAddr, Socket)
 import qualified Network.Socket         as NS
 import           Pipes
 import           Pipes.Network.TCP
                   (fromSocket, fromSocketTimeout, fromSocketN,
-                   fromSocketTimeoutN, toSocket, toSocketTimeout)
+                   fromSocketTimeoutN, toSocket, toSocketLazy, toSocketMany,
+                   toSocketTimeout, toSocketTimeoutLazy, toSocketTimeoutMany)
 import qualified Pipes.Safe             as Ps
 import           Pipes.Safe             (runSafeT)
 
@@ -128,9 +135,7 @@
   -> HostName        -- ^Server host name.
   -> ServiceName     -- ^Server service port.
   -> Producer' B.ByteString m ()
-fromConnect nbytes host port = do
-   connect host port $ \(csock,_) -> do
-      fromSocket csock nbytes
+fromConnect nbytes = _connect (\csock -> fromSocket csock nbytes)
 
 -- | Connects to a TCP server, sends to the remote end the bytes received from
 -- upstream.
@@ -147,10 +152,37 @@
   => HostName        -- ^Server host name.
   -> ServiceName     -- ^Server service port.
   -> Consumer' B.ByteString m r
-toConnect hp port = do
-   connect hp port $ \(csock,_) -> do
-      toSocket csock
+toConnect = _connect toSocket
 
+-- | Like 'toConnect', but works more efficiently on lazy 'BL.ByteString's
+-- (compared to converting them to a strict 'B.ByteString' and sending it)
+toConnectLazy
+  :: Ps.MonadSafe m
+  => HostName        -- ^Server host name.
+  -> ServiceName     -- ^Server service port.
+  -> Consumer' BL.ByteString m r
+toConnectLazy = _connect toSocketLazy
+
+-- | Like 'toConnect', but works more efficiently on @['B.ByteString']@
+-- (compared to converting them to a strict 'B.ByteString' and sending it)
+toConnectMany
+  :: Ps.MonadSafe m
+  => HostName        -- ^Server host name.
+  -> ServiceName     -- ^Server service port.
+  -> Consumer' [B.ByteString] m r
+toConnectMany = _connect toSocketMany
+
+_connect
+  :: Ps.MonadSafe m
+  => (Socket -> m r) -- ^Action to perform on the connection socket.
+  -> HostName        -- ^Server host name.
+  -> ServiceName     -- ^Server service port.
+  -> m r
+_connect act hp port = do
+    connect hp port $ \(csock,_) -> do
+       act csock
+{-# INLINABLE _connect #-}
+
 --------------------------------------------------------------------------------
 
 -- $server-streaming
@@ -189,10 +221,7 @@
   -> HostPreference  -- ^Preferred host to bind.
   -> ServiceName     -- ^Service port to bind.
   -> Producer' B.ByteString m ()
-fromServe nbytes hp port = do
-   listen hp port $ \(lsock,_) -> do
-      accept lsock $ \(csock,_) -> do
-         fromSocket csock nbytes
+fromServe nbytes = _serve (\csock -> fromSocket csock nbytes)
 
 -- | Binds a listening socket, accepts a single connection, sends to the remote
 -- end the bytes received from upstream.
@@ -210,10 +239,39 @@
   => HostPreference  -- ^Preferred host to bind.
   -> ServiceName     -- ^Service port to bind.
   -> Consumer' B.ByteString m r
-toServe hp port = do
+toServe = _serve toSocket
+
+-- | Like 'toServe', but works more efficiently on lazy 'BL.ByteString's
+-- (compared to converting them to a strict 'B.ByteString' and sending it)
+toServeLazy
+  :: Ps.MonadSafe m
+  => HostPreference  -- ^Preferred host to bind.
+  -> ServiceName     -- ^Service port to bind.
+  -> Consumer' BL.ByteString m r
+toServeLazy = _serve toSocketLazy
+
+-- | Like 'toServe', but works more efficiently on @['B.ByteString']@
+-- (compared to converting them to a strict 'B.ByteString' and sending it)
+toServeMany
+  :: Ps.MonadSafe m
+  => HostPreference  -- ^Preferred host to bind.
+  -> ServiceName     -- ^Service port to bind.
+  -> Consumer' [B.ByteString] m r
+toServeMany = _serve toSocketMany
+
+_serve
+  :: Ps.MonadSafe m
+  => (Socket -> m r) -- ^Action to perform on the connection socket.
+  -> HostPreference  -- ^Preferred host to bind.
+  -> ServiceName     -- ^Service port to bind.
+  -> m r
+_serve act hp port = do
    listen hp port $ \(lsock,_) -> do
       accept lsock $ \(csock,_) -> do
-         toSocket csock
+         closeSock lsock -- We prevent more connection attempts to happen
+                         -- while we deal with `csock`.
+         act csock
+{-# INLINABLE _serve #-}
 
 --------------------------------------------------------------------------------
 
@@ -225,15 +283,22 @@
 --    'fromSocketTimeout',
 --    'fromSocketTimeoutN',
 --    'toSocket',
---    'toSocketTimeout'.
+--    'toSocketLazy',
+--    'toSocketMany',
+--    'toSocketTimeout',
+--    'toSocketTimeoutLazy',
+--    'toSocketTimeoutMany'.
 --
 -- [From "Network.Simple.TCP"]
 --    'acceptFork',
 --    'bindSock',
 --    'connectSock',
+--    'closeSock',
 --    'HostPreference'('HostAny','HostIPv4','HostIPv6','Host'),
 --    'recv',
---    'send'.
+--    'send',
+--    'sendLazy',
+--    'sendMany'.
 --
 -- [From "Network.Socket"]
 --    'HostName',
@@ -244,4 +309,3 @@
 --
 -- [From "Pipes.Safe"]
 --    'Ps.runSafeT'.
-
