pas*_*sja 13 haskell buffering xinetd
昨天我给我的学生写了一个小小的xinetd练习:做一个反向回音程序.
为了学习新东西,我试图实现一个Haskell解决方案.琐碎的main = forever $ interact reverse行为不起作用.我仔细检查了这个问题并做了更正后的版本:
import Control.Monad
import System.IO
main = forever $ interact revLines
revLines = unlines . map (reverse) . lines
Run Code Online (Sandbox Code Playgroud)
但是这个更正的版本也行不通.我阅读了缓冲文档并使用各种设置进行了播放.如果我设置NoBuffering或LineBuffering,我的程序正常工作.最后,我打印出stdin和stdout的默认缓冲模式
import System.IO
main = do
hGetBuffering stdin >>= print
hGetBuffering stdout >>= print
Run Code Online (Sandbox Code Playgroud)
我有BlockBuffering Nothing(如果我运行从我的xinetd的程序echo "test" | nc localhost 7),但是从CLI我有LineBuffering
编辑:谢谢大家的有用答案.
我接受了大火给出的答案,他给了我一个isatty的暗示(3).我再次浏览了System.IO文档并找到了hIsTerminalDevice函数,我可以检查句柄的连接.
为了记录,这是我的最终计划:
{-# OPTIONS_GHC -W #-}
import System.IO
main = do
hSetBuffering stdin LineBuffering
hSetBuffering stdout LineBuffering
interact revLines
revLines = unlines . map (reverse) . lines
Run Code Online (Sandbox Code Playgroud)
bla*_*aze 11
它不是特定于Haskell(例如标准C库做同样的事情).传统上,如果文件描述符对应于终端,则缓冲设置为行模式,否则设置为阻止模式.isatty(3)函数可以检查文件描述符类型- 不确定它是否被导出System.IO.
是的,如果你依赖它,你需要手动设置缓冲模式.
顺便说一句,您可以通过运行程序来欺骗系统并在命令行中强制阻止缓冲cat | ./prog | cat.
GHC运行时系统在选择默认缓冲时会尝试变得聪明.如果看起来stdin和stdout直接连接到终端,它们将被行缓冲.如果看起来它们与其他东西相连,则它们是块缓冲的.如果您想要使用不直接来自终端的逐行输入来运行程序,则可能会出现问题.例如,我认为cat | your-program行为与公正不同your-program.
如果我想用两种运行方法编写一个工作程序,我是否必须手动设置缓冲?
是.