
George Russell wrote:
The attached short program (compile with "ghc VServer.hs -o v -package net") is supposed to set up a server on port 15151, wait for a connection, read the first character from the connection, and print it out. Unfortunately if I test it, by running it, and starting up "telnet [machine] 15151" somewhere else, and then type some random text, EG "foo[RETURN]", it does not work. It looks as if the problem is that VServer.hs issues the command hSetBuffering handle (BlockBuffering (Just 4096)) on the connection, because when I change it to hSetBuffering handle NoBuffering the program works.
However this is not what I want to do!! Because setting NoBuffering on the handle is going to mean that when the Server *outputs* something, it will potentially be done very expensively character by character. How do I get block buffering on the Server's output, but not have input to the server held up?
Try using the low-level accept function in Network.Socket, calling
socketToHandle twice to get separate read/write streams, e.g.
accept2 :: Socket -> IO (Handle, Handle, HostName, PortNumber)
accept2 sock = do
~(sock', (SockAddrInet port haddr)) <- Network.Socket.accept sock
(HostEntry peer _ _ _) <- getHostByAddr AF_INET haddr
handle'r <- socketToHandle sock' ReadMode
handle'w <- socketToHandle sock' WriteMode
return (handle'r, handle'w, peer, port)
[This is untested, so I may have overlooked something.]
More generally, many of the higher-level I/O functions have been
over-simplified to the point where they're unsuitable for real-world
use.
--
Glynn Clements