Network

network-2.6.2.1: Low-level networking interface

Copyright | (c) The University of Glasgow 2001
License | BSD-style (see the file libraries/network/LICENSE)
Maintainer | libraries@haskell.org
Stability | provisional
Portability | portable
Safe Haskell | None
Language | Haskell98

Network

Contents

- Basic data types
- Initialisation
- Server-side connections
- Client-side connections
- Simple sending and receiving
- Miscellaneous
- Networking Issues
  - Buffering
  - Improving I/O Performance over sockets
  - `SIGPIPE`

Description

This module is kept for backwards-compatibility. New users are encouraged to use Network.Socket instead.

Network was intended as a "higher-level" interface to networking facilities, and only supports TCP.

Synopsis

- data Socket
- data PortID
  - = Service String
  - | PortNumber PortNumber
  - | UnixSocket String
- type HostName = String
- data PortNumber
- withSocketsDo :: IO a -> IO a
- listenOn :: PortID -> IO Socket
- accept :: Socket -> IO (Handle, HostName, PortNumber)
- sClose :: Socket -> IO ()
- connectTo :: HostName -> PortID -> IO Handle
- sendTo :: HostName -> PortID -> String -> IO ()
- recvFrom :: HostName -> PortID -> IO String
- socketPort :: Socket -> IO PortID

# Basic data types

data Socket

Represents a socket. The fields are, respectively:

- File descriptor
- Socket family
- Socket type
- Protocol number
- Status flag

If you are calling the `MkSocket` constructor directly you should ensure you have called `withSocketsDo`.

Instances

Eq Socket |
Show Socket |

data PortID

Constructors

Service String |
PortNumber PortNumber |
UnixSocket String |

Instances

Eq PortID |
Show PortID |

type HostName = String

Either a host name e.g., `"haskell.org"` or a numeric host address string consisting of a dotted decimal IPv4 address or an IPv6 address e.g., `"192.168.0.1"`.

data PortNumber

Use the `Num` instance (i.e. use a literal) to create a `PortNumber` value with the correct network-byte-ordering. You should not use the PortNum constructor. It will be removed in the next release.

Instances

Enum PortNumber |
Eq PortNumber |
Integral PortNumber |
Num PortNumber |
Ord PortNumber |
Real PortNumber |
Show PortNumber |
Storable PortNumber |

# Initialisation

withSocketsDo :: IO a -> IO a

With older versions of the `network` library on Windows operating systems, the networking subsystem must be initialised using `withSocketsDo` before any networking operations can be used. eg.

    main = withSocketsDo $ do {...}

It is fine to nest calls to `withSocketsDo`, and to perform networking operations after `withSocketsDo` has returned.

In newer versions of the `network` library it is only necessary to call `withSocketsDo` if you are calling the `MkSocket` constructor directly. However, for compatibility with older versions on Windows, it is good practice to always call `withSocketsDo` (it's very cheap).

# Server-side connections

listenOn

Arguments

:: PortID | Port Identifier
-> IO Socket | Listening Socket

Creates the server side socket which has been bound to the specified port.

`maxListenQueue` (typically 128) is specified to the listen queue. This is good enough for normal network servers but is too small for high performance servers.

To avoid the "Address already in use" problems, the `ReuseAddr` socket option is set on the listening socket.

If available, the `IPv6Only` socket option is set to 0 so that both IPv4 and IPv6 can be accepted with this socket.

If you don't like the behavior above, please use the lower level `listen` instead.

accept

Arguments

:: Socket | Listening Socket
-> IO (Handle, HostName, PortNumber) | Triple of: read/write `Handle` for communicating with the client, the `HostName` of the peer socket, and the `PortNumber` of the remote connection.

Accept a connection on a socket created by `listenOn`. Normal I/O operations (see System.IO) can be used on the `Handle` returned to communicate with the client. Notice that although you can pass any Socket to Network.accept, only sockets of either AF_UNIX, AF_INET, or AF_INET6 will work (this shouldn't be a problem, though). When using AF_UNIX, HostName will be set to the path of the socket and PortNumber to -1.

sClose :: Socket -> IO ()

Close the socket. All future operations on the socket object will fail. The remote end will receive no more data (after queued data is flushed).

# Client-side connections

connectTo :: HostName -> PortID -> IO Handle

Calling `connectTo` creates a client side socket which is connected to the given host and port. The Protocol and socket type is derived from the given port identifier. If a port number is given then the result is always an internet family `Stream` socket.

# Simple sending and receiving

Send and receive data from/to the given host and port number. These should normally only be used where the socket will not be required for further calls. Also, note that due to the use of `hGetContents` in `recvFrom` the socket will remain open (i.e. not available) even if the function already returned. Their use is strongly discouraged except for small test-applications or invocations from the command line.

sendTo :: HostName -> PortID -> String -> IO ()

recvFrom :: HostName -> PortID -> IO String

# Miscellaneous

socketPort :: Socket -> IO PortID

Returns the `PortID` associated with a given socket.

# Networking Issues

## Buffering

The `Handle` returned by `connectTo` and `accept` is block-buffered by default. For an interactive application you may want to set the buffering mode on the `Handle` to `LineBuffering` or `NoBuffering`, like so:

    h <- connectTo host port
    hSetBuffering h LineBuffering

## Improving I/O Performance over sockets

For really fast I/O, it might be worth looking at the `hGetBuf` and `hPutBuf` family of functions in System.IO.

## `SIGPIPE`

On Unix, when writing to a socket and the reading end is closed by the remote client, the program is normally sent a `SIGPIPE` signal by the operating system. The default behaviour when a `SIGPIPE` is received is to terminate the program silently, which can be somewhat confusing if you haven't encountered this before. The solution is to specify that `SIGPIPE` is to be ignored, using the POSIX library:

     import Posix
     main = do installHandler sigPIPE Ignore Nothing; ...