我正在阅读本教程: http://www.catonmat.net/blog/simple-haskell-tcp-server/ 学习Haskell网络模块的基础知识。他写了一个名为sockHandler的小函数:
sockHandler :: Socket -> IO ()
sockHandler sock = do
(handle, _, _) <- accept sock
hSetBuffering handle NoBuffering
forkIO $ commandProcessor handle
sockHandler sock
接受连接,并将其分配给新线程。在打破代码时,他说:
“接下来我们使用hSetBuffering将客户端套接字句柄的缓冲模式更改为NoBuffering,因此我们没有缓冲惊喜。”
但是没有详细说明这一点。他在谈论什么惊喜?我谷歌了,看到了一些安全性文章(我猜测它与被拦截的缓存有关),但似乎与本教程的内容没什么关系。
问题是什么?我想到了,但我认为我没有足够的网络经验来填补空白。
谢谢。
答案 0 :(得分:5)
为了便于说明,假设协议允许服务器向客户端查询某些信息,例如: (愚蠢的例子如下)
hPutStr sock "Please choose between A or B"
choice <- hGetLine sock
case decode choice of
Just A -> handleA
Just B -> handleB
Nothing -> protocolError
一切看起来都不错......但是服务器似乎挂了。为什么?这是因为消息并非真正通过hPutStr
通过网络发送,而只是插入本地缓冲区。因此,另一端从不接收查询,因此不会回复,导致服务器卡在其读取中。
此处的解决方案是在阅读前插入hFlush sock
。这必须手动插入“右”点,并且容易出错。更懒的选择是完全禁用缓冲 - 这更安全,尽管它会严重影响性能。