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.
- serve :: HostPreference -> ServiceName -> ((Socket, SockAddr) -> IO r) -> IO r
- serveFork :: 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
- connect :: HostName -> ServiceName -> ((Socket, SockAddr) -> IO r) -> IO r
- 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
- bindSock :: HostPreference -> ServiceName -> IO (Socket, SockAddr)
- connectSock :: HostName -> ServiceName -> IO (Socket, SockAddr)
- data HostPreference
- data Timeout = Timeout String
Server side
The following functions allow you to obtain and use Socket
s useful to
the server side of a TCP connection.
Here's how you could run a TCP server that handles in different threads each
incoming connection to port 8000
at address 127.0.0.1
:
listen (Host "127.0.0.1") "8000" $ \(listeningSocket, listeningAddr) -> do putStrLn $ "Listening for incoming connections at " ++ show listeningAddr forever . acceptFork listeningSocket $ \(connectionSocket, remoteAddr) -> do putStrLn $ "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 keep reading you'll discover there are different ways to achieve
the same, some ways more general than others. The above one was just an
example using a pretty general approach, you are encouraged to use simpler
approaches such as serve
if those suit your needs.
:: HostPreference | Preferred host to bind. |
-> ServiceName | Service port to bind. |
-> ((Socket, SockAddr) -> IO r) | Computation to run once an incoming connection is accepted. Takes the connection socket and remote end address. |
-> IO r |
:: 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 uses them concurrently in different threads.
The listening and connection sockets are closed when done or in case of exceptions.
Note: You don't need to use listen
nor acceptFork
if you use this
function.
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.
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.
Client side
The following functions allow you to obtain and use Socket
s useful to
the client side of a TCP connection.
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.
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 at once. |
-> 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.
If the remote peer closes its side of the connection, this proxy returns.
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 at once. |
-> 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.
Low level support
bindSock :: HostPreference -> ServiceName -> IO (Socket, SockAddr)Source
Obtain a Socket
bound to the given host name and TCP service port.
The obtained Socket
should be closed manually using sClose
when
it's not needed anymore.
Prefer to use listen
if you will be listening on this socket and using it
within a limited scope, and would like it to be closed immediately after its
usage or in case of exceptions.
connectSock :: HostName -> ServiceName -> IO (Socket, SockAddr)Source
Obtain a Socket
connected to the given host and TCP service port.
The obtained Socket
should be closed manually using sClose
when
it's not needed anymore, otherwise you risk having the socket open for much
longer than needed.
Prefer to use connect
if you will be using the socket within a limited
scope and would like it to be closed immediately after its usage or in case
of exceptions.
Exports
data HostPreference Source
Preferred host to bind.
HostAny | Any avaiable host. |
HostIPv4 | Any avaiable IPv4 host. |
HostIPv6 | Any avaiable IPv6 host. |
Host HostName | An explicit host name. |
Eq HostPreference | |
Ord HostPreference | |
Read HostPreference | |
Show HostPreference | |
IsString HostPreference | The following special values are recognized: |