Sending multiline message via sockets without closing the connection

Posted by Yasir Arsanukaev on Stack Overflow See other posts from Stack Overflow or by Yasir Arsanukaev
Published on 2010-05-10T13:14:01Z Indexed on 2010/05/10 14:14 UTC
Read the original article Hit count: 347

Filed under:
|
|
|

Hello folks.

Currently I have this code of my client-side Haskell application:

import Network.Socket
import Network.BSD
import System.IO hiding (hPutStr, hPutStrLn, hGetLine, hGetContents)
import System.IO.UTF8

connectserver :: HostName             -- ^ Remote hostname, or localhost
              -> String               -- ^ Port number or name
              -> IO Handle
connectserver hostname port = withSocketsDo $ do
     -- withSocketsDo is required on Windows
     -- Look up the hostname and port.  Either raises an exception
     -- or returns a nonempty list.  First element in that list
     -- is supposed to be the best option.
     addrinfos <- getAddrInfo Nothing (Just hostname) (Just port)
     let serveraddr = head addrinfos

     -- Establish a socket for communication
     sock <- socket (addrFamily serveraddr) Stream defaultProtocol

     -- Mark the socket for keep-alive handling since it may be idle
     -- for long periods of time
     setSocketOption sock KeepAlive 1

     -- Connect to server
     connect sock (addrAddress serveraddr)

     -- Make a Handle out of it for convenience
     h <- socketToHandle sock ReadWriteMode

     -- Were going to set buffering to LineBuffering and then
     -- explicitly call hFlush after each message, below, so that
     -- messages get logged immediately
     hSetBuffering h LineBuffering

     return h

sendid :: Handle
     -> String
     -> IO String
sendid h id = do 
     hPutStr h id
     -- Make sure that we send data immediately
     hFlush h
     -- Retrieve results
     hGetLine h

The code portions in connectserver are from this chapter of Real World Haskell book where they say:

When dealing with TCP data, it's often convenient to convert a socket into a Haskell Handle. We do so here, and explicitly set the buffering – an important point for TCP communication. Next, we set up lazy reading from the socket's Handle. For each incoming line, we pass it to handle. After there is no more data – because the remote end has closed the socket – we output a message about that.

Since hGetContents blocks until the server closes the socket on the other side, I used hGetLine instead. It satisfied me before I decided to implement multiline output to client. I wouldn't like the server to close a socket every time it finishes sending multiline text. The only simple idea I have at the moment is to count the number of linefeeds and stop reading lines after two subsequent linefeeds. Do you have any better suggestions?

Thanks.

© Stack Overflow or respective owner

Related posts about haskell

Related posts about io