socket package:network

Create a new socket using the given address family, socket type and protocol number. The address family is usually AF_INET, AF_INET6, or AF_UNIX. The socket type is usually Stream or Datagram. The protocol number is usually defaultProtocol. If AF_INET6 is used and the socket type is Stream or Datagram, the IPv6Only socket option is set to 0 so that both IPv4 and IPv6 can be handled with one socket.
>>> import Network.Socket

>>> let hints = defaultHints { addrFlags = [AI_NUMERICHOST, AI_NUMERICSERV], addrSocketType = Stream }

>>> addr:_ <- getAddrInfo (Just hints) (Just "127.0.0.1") (Just "5000")

>>> sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)

>>> Network.Socket.bind sock (addrAddress addr)

>>> getSocketName sock
127.0.0.1:5000
This is the main module of the network package supposed to be used with either Network.Socket.ByteString or Network.Socket.ByteString.Lazy for sending/receiving. Here are two minimal example programs using the TCP/IP protocol:
  • a server that echoes all data that it receives back
  • a client using it
-- Echo server program
module Main (main) where

import Control.Concurrent (forkFinally)
import qualified Control.Exception as E
import Control.Monad (unless, forever, void)
import qualified Data.ByteString as S
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)

main :: IO ()
main = runTCPServer Nothing "3000" talk
where
talk s = do
msg <- recv s 1024
unless (S.null msg) $ do
sendAll s msg
talk s

-- from the "network-run" package.
runTCPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a
runTCPServer mhost port server = withSocketsDo $ do
addr <- resolve
E.bracket (open addr) close loop
where
resolve = do
let hints = defaultHints {
addrFlags = [AI_PASSIVE]
, addrSocketType = Stream
}
head <$> getAddrInfo (Just hints) mhost (Just port)
open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
setSocketOption sock ReuseAddr 1
withFdSocket sock setCloseOnExecIfNeeded
bind sock $ addrAddress addr
listen sock 1024
return sock
loop sock = forever $ E.bracketOnError (accept sock) (close . fst)
$ \(conn, _peer) -> void $
-- 'forkFinally' alone is unlikely to fail thus leaking @conn@,
-- but 'E.bracketOnError' above will be necessary if some
-- non-atomic setups (e.g. spawning a subprocess to handle
-- @conn@) before proper cleanup of @conn@ is your case
forkFinally (server conn) (const $ gracefulClose conn 5000)
{-# LANGUAGE OverloadedStrings #-}
-- Echo client program
module Main (main) where

import qualified Control.Exception as E
import qualified Data.ByteString.Char8 as C
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)

main :: IO ()
main = runTCPClient "127.0.0.1" "3000" $ \s -> do
sendAll s "Hello, world!"
msg <- recv s 1024
putStr "Received: "
C.putStrLn msg

-- from the "network-run" package.
runTCPClient :: HostName -> ServiceName -> (Socket -> IO a) -> IO a
runTCPClient host port client = withSocketsDo $ do
addr <- resolve
E.bracket (open addr) close client
where
resolve = do
let hints = defaultHints { addrSocketType = Stream }
head <$> getAddrInfo (Just hints) (Just host) (Just port)
open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
connect sock $ addrAddress addr
return sock
The proper programming model is that one Socket is handled by a single thread. If multiple threads use one Socket concurrently, unexpected things would happen. There is one exception for multiple threads vs a single Socket: one thread reads data from a Socket only and the other thread writes data to the Socket only.
Basic type for a socket.
Build a pair of connected socket objects. On Windows, this function emulates socketpair() using AF_UNIX and a temporary file will remain.
Getting the port of socket. IOError is thrown if a port is not available.
Getting the port of socket.
Socket is closed and a duplicated file descriptor is returned. The duplicated descriptor is no longer subject to the possibility of unexpectedly being closed if the socket is finalized. It is now the caller's responsibility to ultimately close the duplicated file descriptor.
Turns a Socket into an Handle. By default, the new handle is unbuffered. Use hSetBuffering to change the buffering. Note that since a Handle is automatically closed by a finalizer when it is no longer referenced, you should avoid doing any more operations on the Socket after calling socketToHandle. To close the Socket after socketToHandle, call hClose on the Handle. Caveat Handle is not recommended for network programming in Haskell, e.g. merely performing hClose on a TCP socket won't cooperate with peer's gracefulClose, i.e. proper shutdown sequence with appropriate handshakes specified by the protocol.
Socket options for use with setSocketOption and getSocketOption. The existence of a constructor does not imply that the relevant option is supported on your system: see isSupportedSocketOption
Timeout in microseconds. This will be converted into struct timeval on Unix and DWORD (as milliseconds) on Windows.
Socket Types. Some of the defined patterns may be unsupported on some systems: see isSupportedSocketType.
The core typeclass to unify socket addresses.
Pattern for a general socket type.
Used in getAddrInfo hints, for example.
Unsupported socket type, equal to any other types not supported on this system.
Deprecated: Use withFdSocket or unsafeFdSocket instead
Getting my SockAddr.
Get a socket option that gives an Int value.
Get the SocketType of an active socket. Since: 3.0.1.0
Does the SocketOption exist on this system?
Is the SOCK_xxxxx constant corresponding to the given SocketType known on this system? GeneralSocketType values, not equal to any of the named patterns or UnsupportedSocketType, will return True even when not known on this system.
Whether or not UNIX-domain sockets are available. AF_UNIX is supported on Windows since 3.1.3.0. So, this variable is True on all platforms. Since 2.7.0.0.