Safe Haskell | None |
---|
This module exports functions that allow you to safely use Socket
resources acquired and released outside a Proxy
pipeline.
Instead, if want to safely acquire and release resources within the pipeline itself, then you should use the functions exported by Control.Proxy.TCP.Safe.
This module re-exports many functions from Network.Simple.TCP
module in the network-simple
package. You might refer to that
module for more documentation.
- connect :: HostName -> ServiceName -> ((Socket, SockAddr) -> IO r) -> IO r
- serve :: HostPreference -> ServiceName -> ((Socket, SockAddr) -> IO ()) -> IO ()
- listen :: HostPreference -> ServiceName -> ((Socket, SockAddr) -> IO r) -> IO r
- accept :: Socket -> ((Socket, SockAddr) -> IO b) -> IO b
- acceptFork :: Socket -> ((Socket, SockAddr) -> IO ()) -> IO ThreadId
- socketReadS :: Proxy p => Int -> Socket -> () -> Producer p ByteString IO ()
- nsocketReadS :: Proxy p => Socket -> Int -> Server p Int ByteString IO ()
- socketWriteD :: Proxy p => Socket -> x -> p x ByteString x ByteString IO r
- socketReadTimeoutS :: Proxy p => Int -> Int -> Socket -> () -> Producer (EitherP Timeout p) ByteString IO ()
- nsocketReadTimeoutS :: Proxy p => Int -> Socket -> Int -> Server (EitherP Timeout p) Int ByteString IO ()
- socketWriteTimeoutD :: Proxy p => Int -> Socket -> x -> EitherP Timeout p x ByteString x ByteString IO r
- data HostPreference
- data Timeout = Timeout String
Client side
Here's how you could run a TCP client:
connect "www.example.org" "80" $ \(connectionSocket, remoteAddr) -> do putStrLn $ "Connection established to " ++ show remoteAddr -- now you may use connectionSocket as you please within this scope. -- possibly with any of the socketReadS, nsocketReadS or socketWriteD -- proxies explained below.
:: HostName | Server hostname. |
-> ServiceName | Server service port. |
-> ((Socket, SockAddr) -> IO r) | Computation taking the communication socket and the server address. |
-> IO r |
Connect to a TCP server and use the connection.
The connection socket is closed when done or in case of exceptions.
If you prefer to acquire and close the socket yourself, then use
connectSock
and the sClose
function from Network.Socket instead.
Server side
Here's how you can run a TCP server that handles in different threads each
incoming connection to port 8000
at IPv4 address 127.0.0.1
:
serve (Host "127.0.0.1") "8000" $ \(connectionSocket, remoteAddr) -> do putStrLn $ "TCP connection established from " ++ show remoteAddr -- now you may use connectionSocket as you please within this scope. -- possibly with any of the socketReadS, nsocketReadS or socketWriteD -- proxies explained below.
If you need more control on the way your server runs, then you can use more
advanced functions such as listen
, accept
and acceptFork
.
:: HostPreference | Preferred host to bind. |
-> ServiceName | Service port to bind. |
-> ((Socket, SockAddr) -> IO ()) | Computation to run in a different thread once an incoming connection is accepted. Takes the connection socket and remote end address. |
-> IO () |
Start a TCP server that accepts incoming connections and handles them concurrently in different threads.
Any acquired network resources are properly closed and discarded when done or in case of exceptions.
Note: This function performs listen
and acceptFork
, so you don't need to
perform those manually.
Listening
:: HostPreference | Preferred host to bind. |
-> ServiceName | Service port to bind. |
-> ((Socket, SockAddr) -> IO r) | Computation taking the listening socket and the address it's bound to. |
-> IO r |
Bind a TCP listening socket and use it.
The listening socket is closed when done or in case of exceptions.
If you prefer to acquire and close the socket yourself, then use
bindSock
and the listen
and sClose
functions from
Network.Socket instead.
Note: maxListenQueue
is tipically 128, which is too small for high
performance servers. So, we use the maximum between maxListenQueue
and
2048 as the default size of the listening queue. The NoDelay
and
ReuseAddr
options are set on the socket.
Accepting
:: Socket | Listening and bound socket. |
-> ((Socket, SockAddr) -> IO b) | Computation to run once an incoming connection is accepted. Takes the connection socket and remote end address. |
-> IO b |
Accept a single incoming connection and use it.
The connection socket is closed when done or in case of exceptions.
:: Socket | Listening and bound socket. |
-> ((Socket, SockAddr) -> IO ()) | Computation to run in a different thread once an incoming connection is accepted. Takes the connection socket and remote end address. |
-> IO ThreadId |
Accept a single incoming connection and use it in a different thread.
The connection socket is closed when done or in case of exceptions.
Socket streams
Once you have a connected Socket
, you can use the following Proxy
s
to interact with the other connection end using streams.
:: Proxy p | |
=> Int | Maximum number of bytes to receive and send
dowstream at once. Any positive value is fine, the
optimal value depends on how you deal with the
received data. Try using |
-> Socket | Connected socket. |
-> () | |
-> Producer p ByteString IO () |
Receives bytes from the remote end sends them downstream.
Less than the specified maximum number of bytes might be received at once.
This proxy returns if the remote peer closes its side of the connection or EOF is received.
Just like socketReadS
, except each request from downstream specifies the
maximum number of bytes to receive.
:: Proxy p | |
=> Socket | Connected socket. |
-> x | |
-> p x ByteString x ByteString IO r |
Sends to the remote end the bytes received from upstream, then forwards such same bytes downstream.
Requests from downstream are forwarded upstream.
Timeouts
These proxies behave like the similarly named ones above, except support for timing out the interaction with the remote end is added.
:: Proxy p | |
=> Int | Timeout in microseconds (1/10^6 seconds). |
-> Int | Maximum number of bytes to receive and send
dowstream at once. Any positive value is fine, the
optimal value depends on how you deal with the
received data. Try using |
-> Socket | Connected socket. |
-> () | |
-> Producer (EitherP Timeout p) ByteString IO () |
Like socketReadS
, except it throws a Timeout
exception in the
EitherP
proxy transformer if receiving data from the remote end takes
more time than specified.
:: Proxy p | |
=> Int | Timeout in microseconds (1/10^6 seconds). |
-> Socket | Connected socket. |
-> Int | |
-> Server (EitherP Timeout p) Int ByteString IO () |
Like nsocketReadS
, except it throws a Timeout
exception in the
EitherP
proxy transformer if receiving data from the remote end takes
more time than specified.
:: Proxy p | |
=> Int | Timeout in microseconds (1/10^6 seconds). |
-> Socket | Connected socket. |
-> x | |
-> EitherP Timeout p x ByteString x ByteString IO r |
Like socketWriteD
, except it throws a Timeout
exception in the
EitherP
proxy transformer if sending data to the remote end takes
more time than specified.
Exports
data HostPreference
Preferred host to bind.
HostAny | Any available host. |
HostIPv4 | Any available IPv4 host. |
HostIPv6 | Any available IPv6 host. |
Host HostName | An explicit host name. |
Eq HostPreference | |
Ord HostPreference | |
Read HostPreference | |
Show HostPreference | |
IsString HostPreference | The following special values are recognized: |