on master help sign in
Add the Network.Client module
commit81d8c27b313a14a38ceb865e05f1d09f2ef20f8f authorHarendra Kumar <harendra.kumar@gmail.com> dateFri 31 May 2019, 14:06 (7 years ago) parenta2e7676
3 files changed+138−18
examples/FromFileClient.hs+4−18 src/Streamly/Network/Client.hs+133 streamly.cabal+1
examples/FromFileClient.hs+4−18
@@ -3,28 +3,14 @@
33-- * Opens as many concurrent connections to the server
44-- * Sends all the files concurrently to the server
55
6−import Network.Socket
7−import System.IO (openFile, IOMode(..), hClose)
86import System.Environment (getArgs)
97
108import Streamly
119import qualified Streamly.Prelude as S
1210import qualified Streamly.FileSystem.File as File
13−import qualified Streamly.Network.Socket as NS
11+import qualified Streamly.Network.Client as Client
1412
1513main :: IO ()
16−main = getArgs >>= S.drain . parallely . S.mapM sendFile . S.fromList
17−
18− where
19−
20− sendFile file = do
21− h <- openFile file ReadMode
22− openConnection >>= \sk -> do
23− S.drain $ NS.writeArrays sk $ File.readArrays h
24− close sk
25− hClose h
26−
27− openConnection = do
28− sock <- socket AF_INET Stream defaultProtocol
29− connect sock $ SockAddrInet 8090 (tupleToHostAddress (127,0,0,1))
30− return sock
14+main =
15+ let sendFile = Client.writeArrays (127,0,0,1) 8090 . File.readArrays
16+ in getArgs >>= S.drain . parallely . S.mapM sendFile . S.fromList
src/Streamly/Network/Client.hsnew file+133
@@ -0,0 +1,133 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE BangPatterns #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE MagicHash #-}
5+{-# LANGUAGE RecordWildCards #-}
6+{-# LANGUAGE UnboxedTuples #-}
7+
8+#include "inline.hs"
9+
10+-- |
11+-- Module : Streamly.Network.Client
12+-- Copyright : (c) 2019 Composewell Technologies
13+--
14+-- License : BSD3
15+-- Maintainer : harendra.kumar@gmail.com
16+-- Stability : experimental
17+-- Portability : GHC
18+--
19+-- Combinators to build network clients.
20+--
21+-- > import qualified Streamly.Network.Socket as Client
22+--
23+
24+module Streamly.Network.Client
25+ (
26+ -- * Interact
27+ -- | Socket based reads and writes.
28+ withConnection
29+
30+ -- * Source
31+ , read
32+ -- , readUtf8
33+ -- , readLines
34+ -- , readFrames
35+ -- , readByChunks
36+
37+ -- -- * Array Read
38+ -- , readArrayUpto
39+ -- , readArrayOf
40+
41+ -- , readArraysUpto
42+ -- , readArraysOf
43+ -- , readArrays
44+
45+ -- * Sink
46+ , write
47+ -- , writeUtf8
48+ -- , writeUtf8ByLines
49+ -- , writeByFrames
50+ -- , writeByChunks
51+
52+ -- -- * Array Write
53+ -- , writeArray
54+ , writeArrays
55+ )
56+where
57+
58+import Control.Monad.Catch (MonadCatch)
59+import Control.Monad.IO.Class (MonadIO(..))
60+import Data.Word (Word8)
61+import Network.Socket
62+ (Socket, PortNumber, Family(..), SockAddr(..), SocketType(..),
63+ socket, connect, defaultProtocol)
64+import Prelude hiding (read)
65+
66+import qualified Network.Socket as Net
67+
68+import Streamly (MonadAsync)
69+import Streamly.Mem.Array.Types (Array(..))
70+import Streamly.Streams.Serial (SerialT)
71+import Streamly.Streams.StreamK.Type (IsStream)
72+
73+import qualified Streamly.Prelude as S
74+import qualified Streamly.Network.Socket as SK
75+
76+-------------------------------------------------------------------------------
77+-- Connect
78+-------------------------------------------------------------------------------
79+
80+openConnection :: (Word8, Word8, Word8, Word8) -> PortNumber -> IO Socket
81+openConnection addr port = do
82+ sock <- socket AF_INET Stream defaultProtocol
83+ connect sock $ SockAddrInet port (Net.tupleToHostAddress addr)
84+ return sock
85+
86+-- | @'withConnection' addr port act@ opens a connection to the specified IPv4
87+-- host address and port and passes the resulting socket handle to the
88+-- computation @act@. The handle will be closed on exit from 'withConnection',
89+-- whether by normal termination or by raising an exception. If closing the
90+-- handle raises an exception, then this exception will be raised by
91+-- 'withConnection' rather than any exception raised by 'act'.
92+--
93+-- @since 0.7.0
94+withConnection :: (IsStream t, MonadCatch m, MonadIO m)
95+ => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> t m a) -> t m a
96+withConnection addr port =
97+ S.bracket (liftIO $ openConnection addr port) (liftIO . Net.close)
98+
99+-------------------------------------------------------------------------------
100+-- Read Addr to Stream
101+-------------------------------------------------------------------------------
102+
103+-- | Read a stream from the supplied IPv4 host address and port number.
104+--
105+-- @since 0.7.0
106+read :: (IsStream t, MonadCatch m, MonadIO m)
107+ => (Word8, Word8, Word8, Word8) -> PortNumber -> t m Word8
108+read addr port = withConnection addr port SK.read
109+
110+-------------------------------------------------------------------------------
111+-- Writing
112+-------------------------------------------------------------------------------
113+
114+-- | Write a stream to the supplied IPv4 host address and port number.
115+--
116+-- @since 0.7.0
117+write :: (MonadCatch m, MonadIO m)
118+ => (Word8, Word8, Word8, Word8) -> PortNumber -> SerialT m Word8 -> m ()
119+write addr port xs =
120+ S.drain $ withConnection addr port (\sk -> S.yieldM $ SK.write sk xs)
121+
122+-- | Write a stream of arrays to the supplied IPv4 host address and port
123+-- number.
124+--
125+-- @since 0.7.0
126+writeArrays
127+ :: (MonadCatch m, MonadAsync m)
128+ => (Word8, Word8, Word8, Word8)
129+ -> PortNumber
130+ -> SerialT m (Array Word8)
131+ -> m ()
132+writeArrays addr port xs =
133+ S.drain $ withConnection addr port (\sk -> S.yieldM $ SK.writeArrays sk xs)
streamly.cabal+1
@@ -219,6 +219,7 @@ library
219219 , Streamly.FileSystem.Handle
220220 , Streamly.Network.Socket
221221 , Streamly.Network.Server
222+ , Streamly.Network.Client
222223
223224 -- Time
224225 , Streamly.Time.Units