diff --git a/Network/Run/UDP.hs b/Network/Run/UDP.hs
--- a/Network/Run/UDP.hs
+++ b/Network/Run/UDP.hs
@@ -2,10 +2,15 @@
 module Network.Run.UDP (
     runUDPClient
   , runUDPServer
+  , runUDPServerFork
   ) where
 
+import Control.Concurrent (forkIO, forkFinally)
 import qualified Control.Exception as E
+import Control.Monad (forever, void)
+import Data.ByteString (ByteString)
 import Network.Socket
+import Network.Socket.ByteString
 
 import Network.Run.Core
 
@@ -19,8 +24,39 @@
     let sockAddr = addrAddress addr
     E.bracket (openSocket addr) close $ \sock -> client sock sockAddr
 
--- | Running a UDP server with an open socket.
+-- | Running a UDP server with an open socket in a single Haskell thread.
 runUDPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a
 runUDPServer mhost port server = withSocketsDo $ do
     addr <- resolve Datagram mhost port True
     E.bracket (openServerSocket addr) close server
+
+-- | Running a UDP server with a connected socket in each Haskell thread.
+--   The first request is given to the server.
+--   Suppose that the server is serving on __addrS:portS__ and
+--   a client connects to the service from __addrC:portC__.
+--   A connected socket is created by binding to __*:portS__ and
+--   connecting to __addrC:portC__,
+--   resulting in __(UDP,addrS:portS,addrC:portC)__ where
+--   __addrS__ is given magically.
+--   This approach is fragile due to NAT rebidings.
+runUDPServerFork :: [HostName] -> ServiceName -> (Socket -> ByteString -> IO ()) -> IO ()
+runUDPServerFork [] _ _ = return ()
+runUDPServerFork (h:hs) port server = do
+    mapM_ (forkIO . run) hs
+    run h
+  where
+    run host = runUDPServer (Just host) port $ \lsock -> forever $ do
+        (bs0,peeraddr) <- recvFrom lsock 2048
+        let family = case peeraddr of
+              SockAddrInet{}  -> AF_INET
+              SockAddrInet6{} -> AF_INET6
+              _                 -> error "family"
+            hints = defaultHints {
+                addrSocketType = Datagram
+              , addrFamily = family
+              , addrFlags = [AI_PASSIVE]
+              }
+        addr <- head <$> getAddrInfo (Just hints) Nothing (Just port)
+        s <- openServerSocket addr
+        connect s peeraddr
+        void $ forkFinally (server s bs0) (\_ -> close s)
diff --git a/network-run.cabal b/network-run.cabal
--- a/network-run.cabal
+++ b/network-run.cabal
@@ -1,5 +1,5 @@
 name:                network-run
-version:             0.2.1
+version:             0.2.2
 synopsis:            Simple network runner library
 description:         Simple functions to run network clients and servers.
 -- bug-reports:
@@ -19,6 +19,7 @@
   -- other-extensions:
   build-depends:       base >= 4 && < 5
                      , network >= 3.1.0
+                     , bytestring
   -- hs-source-dirs:
   default-language:    Haskell2010
 
