为什么在以下示例中不应使用缓冲?

时间:2014-07-22 19:24:05

标签: haskell networking buffer

我正在阅读本教程: 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,因此我们没有缓冲惊喜。”

但是没有详细说明这一点。他在谈论什么惊喜?我谷歌了,看到了一些安全性文章(我猜测它与被拦截的缓存有关),但似乎与本教程的内容没什么关系。

问题是什么?我想到了,但我认为我没有足够的网络经验来填补空白。

谢谢。

1 个答案:

答案 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。这必须手动插入“右”点,并且容易出错。更懒的选择是完全禁用缓冲 - 这更安全,尽管它会严重影响性能。