Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hGetContents vs hGetLine

I have a program in Haskell that get all input from socket and print it.

     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

But the problem is that this solution is closing a socket, but I want to write out the results of computation to the same socket. But if I try to use hGetLine instead hGetContents I faced with some strange behaviour. My program show nothing until I press Ctrl-C, and then I see the first line of my network data sended. I suggest that this behaviour related with lasy execution, but why hGetContents works as expected and hGetLine not?

like image 548
Sergey Sosnin Avatar asked Sep 12 '25 07:09

Sergey Sosnin


1 Answers

You need to use LineBuffering if you want to read line-by-line using hGetLine. I got it working with

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

And tested it using the python script

import socket

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

And I got the output

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

And I get the same behavior if I change it to NoBuffering and hGetContents

like image 89
bheklilr Avatar answered Sep 13 '25 22:09

bheklilr