昨天我为我的学生们写了一个小的xinetd练习:制作一个反转回声程序。
为了学习新知识,我尝试实现了Haskell的解决方案。简单的main = forever $ interact reverse
是不起作用的。我查阅了这个问题,并制作了一个更正后的版本:
import Control.Monad
import System.IO
main = forever $ interact revLines
revLines = unlines . map (reverse) . lines
但是这个更正的版本也不起作用。我阅读了缓冲文档,并尝试了各种设置。
如果我将 NoBuffering
或者 LineBuffering
设置上,程序就可以正确运行。最后我打印了stdin和stdout的默认缓冲模式。
import System.IO
main = do
hGetBuffering stdin >>= print
hGetBuffering stdout >>= print
如果我从xinetd运行我的程序(echo "test" | nc localhost 7
),则使用BlockBuffering Nothing
,但是如果我从cli运行,则使用LineBuffering
- 就缓冲而言,xinetd tcp服务和cli程序有什么区别?
- 如果我想编写同时适用于两种运行方法的工作程序,是否需要手动设置缓冲?
编辑:感谢所有提供有用答案的人。
我接受blaze给出的答案,他提示我使用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
forever
。由于惰性,interact
将继续等待输入,并且对于从stdin
读取的每一行完整数据,它的倒序都会立即被打印出来。 - tempestadeptLineBuffering
可能会得到最佳效果。 - J. Abrahamson