hGetContents vs hGetLine

时间:2014-07-30 15:30:44

标签: sockets haskell networking

我在Haskell中有一个程序可以从套接字获取所有输入并打印它。

     main = withSocketsDo $ do
            sock <- listenOn $ PortNumber 5002
            netLoop sock

        netLoop sock = do
           (h,_,_) <- accept sock
           hSetBuffering h NoBuffering
           forkIO $ workLoop h
           netLoop sock


        workLoop :: Handle -> IO ()
        workLoop h = do
        str <- hGetContents h   
        putStr str
        --do any work

但问题是这个解决方案正在关闭套接字,但我想把计算结果写到同一个套接字上。 但是,如果我尝试使用hGetLine代替hGetContents,我会遇到一些奇怪的行为。直到我按下Ctrl-C,我的程序才显示任何内容,然后我看到我的网络数据的第一行被发送。我建议这种行为与la​​sy执行有关,但为什么hGetContents按预期工作而hGetLine不工作?

1 个答案:

答案 0 :(得分:7)

如果您想使用LineBuffering逐行阅读,则需要使用hGetLine。我使用了

import Network
import System.IO
import Control.Concurrent

main :: IO ()
main = withSocketsDo $ do
    sock <- listenOn $ PortNumber 5002
    netLoop sock

netLoop :: Socket -> IO ()
netLoop sock = do
    putStrLn "Accepting socket"
    (h,_,_) <- accept sock
    putStrLn "Accepted socket"
    hSetBuffering h LineBuffering
    putStrLn "Starting workLoop"
    forkIO $ workLoop h
    netLoop sock


workLoop :: Handle -> IO ()
workLoop h = do
    putStrLn "workLoop started"
    str <- hGetLine h
    putStrLn $ "Read text: " ++ str
    -- do any work

使用python脚本

测试它
import socket

s = socket()
s.connect(('127.0.0.1', 5002))
s.send('testing\n')
s.close()

我得到了输出

Accepting socket
Accepted socket
Starting workLoop
workLoop started
Accepting socket
Read text: testing

如果我将其更改为NoBufferinghGetContents

,我会得到相同的行为