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.