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: 382
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