Safe Haskell | None |
---|
Network.Simple.TCP
Contents
Description
This module exports functions that abstract simple TCP Socket
usage patterns.
- 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
- bindSock :: HostPreference -> ServiceName -> IO (Socket, SockAddr)
- connectSock :: HostName -> ServiceName -> IO (Socket, SockAddr)
- data HostPreference
Introduction to TCP networking
This introduction aims to give you a overly simplified overview of some concepts you need to know about TCP sockets in order to make effective use of this module.
There are two ends in a single TCP connection: one is the TCP «server» and the other is the TCP «client». Each end is uniquely identified by an IP address and a TCP port pair, and each end knows the IP address and TCP port of the other end. Each end can send and receive data to and from the other end.
A TCP server, once «bound» to a well-known IP address and TCP port, starts «listening» for incoming connections from TCP clients to such bound IP address and TCP port. When a TCP client attempts to connect to the TCP server, the TCP server must «accept» the incoming connection in order to start exchanging data with the remote end. A single TCP server can sequentially accept many incoming connections, possibly handling each one concurrently.
A TCP client can «connect» to a well-known IP address and TCP port previously bound by a listening TCP server willing to accept new incoming connections. Once the connection is established, the TCP client can immediately start exchanging data with the TCP server. The TCP client is randomly assigned a TCP port when connecting, and its IP address is selected by the operating system so that it is reachable from the remote end.
The TCP client a and the TCP server can be running in the same host or in different hosts.
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.
Arguments
:: 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.
If you need more control on the way your server runs, then you can use more
advanced functions such as listen
, accept
and acceptFork
.
Arguments
:: 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
Arguments
:: 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
Arguments
:: 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.
Arguments
:: 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.
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.
Constructors
HostAny | Any available host. |
HostIPv4 | Any available IPv4 host. |
HostIPv6 | Any available IPv6 host. |
Host HostName | An explicit host name. |
Instances
Eq HostPreference | |
Ord HostPreference | |
Read HostPreference | |
Show HostPreference | |
IsString HostPreference | The following special values are recognized: |