Reputation: 21716
I am in the midst of porting the amqp package from using GHC.IO.Handle to using Network.Connection.Connection. The motivation for this is to gain transparent SSL/TLS support to allow for encrypted AMQP communications from Haskell.
The trouble is that my Connnection-based implementation doesn't work. I was running into some fairly surprising (to me) differences when I packet trace the alternate implementations.
It became evident that Network.Connection.connectionGet and GHC.IO.Handle.hGet are very different (non-blocking vs blocking):
http://hackage.haskell.org/package/connection-0.1.3.1/docs/Network-Connection.html#v:connectionGet http://hackage.haskell.org/package/bytestring-0.10.4.0/docs/Data-ByteString-Lazy.html#v:hGet
Network.Connection.connectionGet acts like GHC.IO.Handle.hGetNonBlocking.
I was replacing GHC.IO.Handle.hGet with Network.Connection.connectionGet thinking it was a drop-in replacement which it isn't.
How do I use Network.Connection.connectionGet in a blocking manner like Data.ByteString.Lazy.hGet?
Upvotes: 0
Views: 98
Reputation: 33657
I wouldn't call this a blocking vs non-blocking thing as that thought lead to the async IO concept which a different concept then what is happening in these APIs.
The difference here is that in hGet
when you ask for x
number of bytes to be read, it will try to read and wait till it gets that number of bytes from the connection OR the connection get closed, where as the connectionGet
function will return whatever bytes it can read from the connection buffer but the count of these bytes will be less than or equals to requested bytes i.e x
.
You can make connectionGet
behave like hGet
using a simple recursion as shown below, NOTE: below has been verified to work :)
import qualified Network.Connection as Conn
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BC
-- ... intervening code
connectionGet' :: Conn.Connection -> Int -> IO BC.ByteString
connectionGet' conn x = do
bs <- Conn.connectionGet conn x
let diff = BS.length bs - x
if BS.length bs == 0 || diff == 0
then do
return bs
else do
next <- connectionGet' conn diff
return $ BC.append bs next
Upvotes: 2