2

I was reading this tutorial: http://www.catonmat.net/blog/simple-haskell-tcp-server/ To learn the basics of Haskell's Network module. He wrote a small function called sockHandler:

sockHandler :: Socket -> IO ()
sockHandler sock = do
    (handle, _, _) <- accept sock
    hSetBuffering handle NoBuffering
    forkIO $ commandProcessor handle
    sockHandler sock

That accepts a connection, and forks it to a new thread. While breaking down the code, he says:

"Next we use hSetBuffering to change buffering mode for the client's socket handle to NoBuffering, so we didn't have buffering surprises."

But doesn't elaborate on that point. What surprises is he talking about? I Google'd it, and saw a few security articles (Which I'm guessing is related to the cache being intercepted), but nothing seemingly related to the content of this tutorial.

What is the issue? I thought about it, but I don't think I have enough networking experience to fill in the blanks.

Thank you.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
  • To avoid [surprises](http://stackoverflow.com/questions/19513660/why-doesnt-haskell-sequence-these-io-actions-properly) like these. But operating it with `NoBuffering` will be inefficient. The proper way IMO would be consume them forcefully with buffering enabled or use `pipes-network` or the conduit version of that. – Sibi Jul 22 '14 at 19:35
  • @Sibi So it could equate to data being received in the wrong order? And at this point, efficiency is the least of my concerns; especially considering I don't understand what any of the alternatives you suggested even mean. If my above understanding is correct, and you post your response as an answer, I'll gladly accept it. – Carcigenicate Jul 22 '14 at 20:01

1 Answers1

5

For the sake of illustration, suppose the protocol allows the server to query the client for some information, e.g. (silly example follows)

 hPutStr sock "Please choose between A or B"
 choice <- hGetLine sock
 case decode choice of
    Just A -> handleA
    Just B -> handleB
    Nothing -> protocolError

Everything looks fine... but the server seems to hang. Why? This is because the message was not really sent over the network by hPutStr, but merely inserted in a local buffer. Hence, the other end never receives the query, so does not reply, causing the server to get stuck in its read.

A solution here would be to insert an hFlush sock before reading. This has to be manually inserted at the "right" points, and is prone to error. A lazier option would be to disable buffering entirely -- this is safer, albeit it severely impacts performance.

chi
  • 111,837
  • 3
  • 133
  • 218
  • So, flushing the buffer causes any cached data to be forcibly sent if it's "stuck" locally? If buffering was set to LineBuffering though, couldn't you have output a \n at the end? Then you have the advantage of LineBuffering, and it wouldn't have gotten caught (unless the example is too contrived to fully represent the problem). Either way, thank you. That makes sense now. – Carcigenicate Jul 23 '14 at 00:44
  • Nvm, I realized that outputting a newline basically just flushes it so the end result is the same. Thank you. – Carcigenicate Jul 23 '14 at 00:48