I'd tried to use
hGetContentsand just read off one message at a time. This is doomed to failure because laziness and hanging around on a network socket that's in a semi-closed state just isn't going to work.
In this version of the code we enter a loop which terminates once the client sends the "quit" message (rather than an infinite loop).
(Update: Thanks to helpful comments edited the code to use
listenLoop :: Handle -> IO ()
listenLoop h = do
sendFrame h "hi, remember you can stop this at anytime by pressing quit!"
msg <- readFrame h
when (msg /= "quit") (listenLoop h)
readFrame :: Handle -> IO String
readFrame h = readUntil h ""
readUntil h str = do
new <- hGetChar h
if (new == chr 0)
then readUntil h ""
else if new == chr 255
then return str
else readUntil h (str ++ [new])
On a side note - the indentation for the if/then/else is a little strange, but "if within do" at least explains why.
All that remains is a quick bit of HTML to allow you to have a conversation. Replace the body in the previous example with something like this (and also make sure that the
wsobject has the appropriate scope!
<h1>I'm doing something</h1>
<textarea rows="2" cols="80" id="message">
Type whatever you want here, but type quit to close the connection
<button id="clickMe" onClick="ws.send($('#message').val());">
You should get something where you can have a rather boring conversation with Haskell. It repeats the same text over and over again until you press quit.