Stability | experimental |
---|---|
Maintainer | Nils Schweinsberg <mail@nils.cc> |
Safe Haskell | None |
Easy to use network streaming with conduits. This library properly encodes conduit blocks over a network connection such that
It also supports sending and receiving of custom data types via the
Sendable
and Receivable
instances.
A simple server/client example (using -XOverloadedStrings
):
import Control.Monad.Trans import qualified Data.ByteString as Strict import qualified Data.ByteString.Lazy as Lazy import Data.Conduit import qualified Data.Conduit.List as CL import Data.Conduit.Network import Data.Conduit.Network.Stream client :: IO () client = runResourceT $ runTCPClient (clientSettings ..) $ \appData -> do streamData <- toStreamData appData send streamData $ mapM_ yield (["ab", "cd", "ef"] :: [Strict.ByteString]) send streamData $ mapM_ yield (["123", "456"] :: [Strict.ByteString]) closeStream streamData server :: IO () server = runResourceT $ runTCPServer (serverSettings ..) $ \appData -> do streamData <- toStreamData appData bs <- receive streamData $ CL.consume liftIO $ print (bs :: [Lazy.ByteString]) bs' <- receive streamData $ CL.consume liftIO $ print (bs' :: [Lazy.ByteString]) closeStream streamData
- data StreamData m
- toStreamData :: MonadIO n => AppData m -> n (StreamData m)
- closeStream :: MonadResource m => StreamData m -> m ()
- send :: (Monad m, Sendable m a) => StreamData m -> Source m a -> m ()
- class Sendable m a where
- data EncodedBS
- receive :: (MonadResource m, Receivable a m) => StreamData m -> Sink a m b -> m b
- class Receivable a m where
- decode :: Conduit ByteString m a
- streamSink :: (Monad m, Sendable m a) => StreamData m -> Sink a m ()
- withElementSink :: (Monad m, Sendable m a) => StreamData m -> (Sink a m () -> Sink b m c) -> Sink b m c
Network streams
data StreamData m Source
toStreamData :: MonadIO n => AppData m -> n (StreamData m)Source
closeStream :: MonadResource m => StreamData m -> m ()Source
Close current stream. In order to guarantee process resource finalization,
you must use this operator after using receive
.
Sending
class Sendable m a whereSource
To define your own Sendable
instances, reuse the instances for strict and
lazy bytestrings, for example for Data.Text:
instance (Monad m, Sendable m Data.ByteString.ByteString) => Sendable m Text where encode = Data.Conduit.List.map encodeUtf8 =$= encode
encode :: Conduit a m EncodedBSSource
encode
is called before sending out conduit block elements. Each
element has to be encoded either as strict ByteString
or as lazy ByteString
with a known length.
Monad m => Sendable m ByteString | Instance for lazy bytestrings which calculates the length of the
|
Monad m => Sendable m ByteString | Instance for strict bytestrings, using a specialized version of |
Monad m => Sendable m (Int, ByteString) | Instance for lazy bytestrings with a known length, using a specialized
version of |
Receiving
receive :: (MonadResource m, Receivable a m) => StreamData m -> Sink a m b -> m bSource
Receive the next conduit block. Might fail with the ClosedStream
exception if used on a stream that has been closed by closeStream
.
class Receivable a m whereSource
decode
is used after receiving the individual conduit block elements.
It is therefore not necessary to reuse other decode
instances (in
contrast to Sendable
instance definitions).
decode :: Conduit ByteString m aSource
Monad m => Receivable ByteString m | For lazy bytestrings, |
Monad m => Receivable ByteString m | Instance for strict bytestrings. Note that this uses |
Bi-directional conversations
streamSink :: (Monad m, Sendable m a) => StreamData m -> Sink a m ()Source
For bi-directional conversations you sometimes need the sink of the current
stream, since you can't use send
within another receive
.
A simple example:
receive streamData $ myConduit =$ streamSink streamData
Note, that each streamSink
marks its own conduit block. If you want to sink
single block elements, use withElementSink
instead.
withElementSink :: (Monad m, Sendable m a) => StreamData m -> (Sink a m () -> Sink b m c) -> Sink b m cSource
Sink single elements inside the same conduit block. Example:
receive streamData $ withElementSink $ \sinkElem -> do yield singleElem =$ sinkElem mapM_ yield moreElems =$ sinkElem