diff --git a/Data/Enumerator/NetLines.hs b/Data/Enumerator/NetLines.hs
--- a/Data/Enumerator/NetLines.hs
+++ b/Data/Enumerator/NetLines.hs
@@ -26,10 +26,11 @@
       netSplitBy,
       netSplitsBy,
 
-      -- * Enumerators
+      -- * Input/output
       TimeoutError(..),
       enumHandleSession,
-      enumHandleTimeout
+      enumHandleTimeout,
+      iterHandleTimeout
     )
     where
 
@@ -43,6 +44,7 @@
 import Data.Word
 import System.IO
 import System.IO.Error as IOErr
+import System.Timeout
 
 
 -- | Exception for timed out IO operations.
@@ -72,7 +74,7 @@
     loop :: UTCTime -> Enumerator ByteString m b
     loop startTime (Continue k) = do
         now <- liftIO getCurrentTime
-        let timeoutErr = TimeoutError "Reading from handle"
+        let timeoutErr = TimeoutError "Read timeout"
             diff = sessionTime - round (1000 * diffUTCTime now startTime)
             timeout = min diff readTime
         when (timeout <= 0) $ throwError timeoutErr
@@ -83,8 +85,7 @@
               | otherwise      -> throwError err
           Right False -> throwError timeoutErr
           Right True  -> do
-              mStr <- liftIO $ IOErr.try (B.hGetNonBlocking h bufSize)
-              str <- either throwError return mStr
+              str <- tryIO $ B.hGetNonBlocking h bufSize
               if B.null str
                 then continue k
                 else k (Chunks [str]) >>== loop startTime
@@ -112,10 +113,9 @@
           Left err
               | isEOFError err -> continue k
               | otherwise      -> throwError err
-          Right False -> throwError $ TimeoutError "Reading from handle"
+          Right False -> throwError $ TimeoutError "Read timeout"
           Right True  -> do
-              mStr <- liftIO $ IOErr.try (B.hGetNonBlocking h bufSize)
-              str <- either throwError return mStr
+              str <- tryIO $ B.hGetNonBlocking h bufSize
               if B.null str
                 then continue k
                 else k (Chunks [str]) >>== loop
@@ -128,6 +128,36 @@
 isSpace n = n == 32 || (n >= 9 && n <= 13)
 
 
+-- | Writes its inputs to the given handle.  Times out after the given
+-- number of milliseconds with a 'TimeoutError' iteratee exception.  The
+-- handle should be unbuffered and in binary mode.  See 'hSetBuffering'
+-- and 'hSetBinaryMode'.
+--
+-- Please note that only the write operations themselves are timed.
+-- Most notably the operation of the data source enumerator is *not*
+-- timed.  Hence the operation may time out later than the given time
+-- margin, but never earlier.
+
+iterHandleTimeout ::
+    forall m. MonadIO m => Int -> Handle -> Iteratee ByteString m ()
+iterHandleTimeout maxTime h = do
+    startTime <- tryIO getCurrentTime
+    continue (loop startTime)
+
+    where
+    loop :: UTCTime -> Stream ByteString -> Iteratee ByteString m ()
+    loop _ EOF = yield () EOF
+    loop startTime (Chunks []) = continue (loop startTime)
+    loop startTime (Chunks strs) = do
+        let timeoutErr = TimeoutError "Write timeout"
+        now <- tryIO getCurrentTime
+        let restMs = 1000*maxTime - round (1000000 * diffUTCTime now startTime)
+        when (restMs <= 0) (throwError timeoutErr)
+        tryIO (timeout restMs (mapM_ (B.hPutStr h) strs)) >>=
+            maybe (throwError timeoutErr) return
+        continue (loop startTime)
+
+
 -- | Get the next nonempty line from the stream using 'netLineEmpty'.
 
 netLine :: forall m. Monad m => Int -> Iteratee ByteString m (Maybe ByteString)
@@ -164,17 +194,16 @@
     (Word8 -> Bool) -> (Word8 -> Bool) -> Int ->
     Iteratee ByteString m (Maybe ByteString)
 netSplitBy breakP filterP n =
-    continue (loop n B.empty)
+    continue (loop B.empty)
 
     where
-    loop :: Int -> ByteString -> Stream ByteString ->
+    loop :: ByteString -> Stream ByteString ->
             Iteratee ByteString m (Maybe ByteString)
-    loop _ line' EOF = yield (if B.null line' then Nothing else Just line') EOF
-    loop 0 line' (Chunks _) = continue (loop 0 line')
-    loop n line' (Chunks []) = continue (loop n line')
-    loop n' line' (Chunks (str:strs)) =
+    loop line' EOF = yield (if B.null line' then Nothing else Just line') EOF
+    loop line' (Chunks []) = continue (loop line')
+    loop line' (Chunks (str:strs)) =
         if B.null line2'
-          then line `seq` loop n line (Chunks strs)
+          then line `seq` loop line (Chunks strs)
           else yield (Just line) (Chunks (line2:strs))
 
         where
@@ -182,7 +211,6 @@
         line1            = B.filter filterP line1'
         line2            = B.tail line2'
         line             = B.take n $ B.append line' line1
-        n                = max 0 (n' - B.length line1)
 
 
 -- | Split the stream using the supplied iteratee.
diff --git a/netlines.cabal b/netlines.cabal
--- a/netlines.cabal
+++ b/netlines.cabal
@@ -1,5 +1,5 @@
 Name:          netlines
-Version:       0.4.0
+Version:       0.4.3
 Category:      Network
 Synopsis:      Enumerator tools for text-based network protocols
 Maintainer:    Ertugrul Söylemez <es@ertes.de>
@@ -22,7 +22,7 @@
         base >= 4 && < 5,
         bytestring >= 0.9.1.7,
         contstuff >= 1.2.4,
-        enumerator >= 0.4.7,
+        enumerator >= 0.4.9.1,
         time >= 1.2.0.3
     GHC-Options: -W
     Exposed-modules:
