nschoe
nschoe

Reputation: 2037

How can I get info/examples about Network.Socket{.ByteString}?

I have played a bit with the Network library, the "simple" form where the use is fairly easy: a combination of 'listenOn', 'connectTo', 'accept' and we have something working. Now I am trying to use the "real" thing, meaning Network.Socket and Network.Socket.ByteString because I'd like to send files between a client and a server. But it is not as easy to use as the higher level interface and I'm looking for some code examples and/or how-tos. Particularly, the code dealing with 'getAddrInfo', 'AddrInfo' and 'SockAddr' I don't understand very deeply.
So, where can I get this type of resource?

Upvotes: 1

Views: 364

Answers (3)

Zhen
Zhen

Reputation: 4283

I can just show an own example:

import Network.Socket
  ( SocketType(..), AddrInfo(..), AddrInfoFlag(..), Family(..), socket, sClose, 
    defaultHints, withSocketsDo, connect, getAddrInfo, defaultProtocol )
import Network.Socket.ByteString( sendAll, recv )
import qualified Data.ByteString.Char8 as BC( readFile, hPut, null )

sendFile :: String -> Int -> FilePath -> IO Bool
sendFile server port filename = withSocketsDo $ do
  addrinfos <- getAddrInfo desiredAddr (Just server) (Just . show $ port)
  if null addrinfos
    then do
      return False
    else do
      datafile <- BC.readFile filename
      let serveraddr = head addrinfos
      sock <- socket (addrFamily serveraddr) Stream defaultProtocol
      connect sock (addrAddress serveraddr)
      sendAll sock datafile
      sClose sock
      return True

I don't test (just cut from my code file) so maybe fails in the imports. On the server I use:

readerThread :: MyQueue -> Socket -> IO ()
readerThread queue serverSock = do
  (connsock, clientaddr) <- accept serverSock
  sClose serverSock
  putStrLn $ "> connected reader " ++ show clientaddr
  talk connsock
  sClose connsock
  putStrLn $ "> closed reader " ++ show clientaddr
  return ()
    where
      talk conn = do 
        msg <- recv conn 2048
        putStr $ "* get from " ++ show conn ++ "\n"
        myQueueWrite queue msg
        unless (B.null msg) $ do 
          talk conn

createInputPort :: ChildLocks -> MyQueue -> AddrInfo -> IO PortNumber
createInputPort children obuffer serverAddr = withSocketsDo $ do
  serverSock <- socket AF_INET Stream defaultProtocol
  bindSocket serverSock (addrAddress serverAddr)
  listen serverSock 1

  lock <- newChildLock children
  _ <- forkIO $ readerThread obuffer serverSock `finally` endChildLock lock
  socketPort serverSock

Y use a own queue (TCHAN) to comunicate between network reader an consumer thread, and childLocks to wait at the end with something like waitForChildren children construct that I found on stackoverflow.

UPDATE: the waitForChildren is on post Comparing Haskell threads to kernel threads - is my benchmark viable?

Upvotes: 1

Thomas M. DuBuisson
Thomas M. DuBuisson

Reputation: 64740

The .Socket interface is little more than bindings to berkeley sockets, I suggest you read Beej's guide to network programming (for C) to get a handle on this.

EDIT: The pharse "little more than" isn't intended to slight the amount of work that goes into making this layer configure, build, and install smoothly on all the supported platforms. I'm just saying there's basically a one-to-one relation between many of the .Socket operations and the man (3) pages for the C primitives.

Upvotes: 1

tibbe
tibbe

Reputation: 9009

There's an example at the bottom of the documentation for the Network.Socket.ByteString module.

Upvotes: 1

Related Questions