Я могу просто показать собственный пример:
import Network.Socket
( SocketType(..), AddrInfo(..), AddrInfoFlag(..), Family(..), socket, sClose,
defaultHints, withSocketsDo, connect, getAddrInfo, defaultProtocol )
import Network.Socket.ByteString( sendAll, recv )
import qualified Data.ByteString.Char8 as BC( readFile, hPut, null )
sendFile :: String -> Int -> FilePath -> IO Bool
sendFile server port filename = withSocketsDo $ do
addrinfos <- getAddrInfo desiredAddr (Just server) (Just . show $ port)
if null addrinfos
then do
return False
else do
datafile <- BC.readFile filename
let serveraddr = head addrinfos
sock <- socket (addrFamily serveraddr) Stream defaultProtocol
connect sock (addrAddress serveraddr)
sendAll sock datafile
sClose sock
return True
Я не тестирую (просто вырезал из моего файла кода), поэтому, возможно, произойдет сбой при импорте.На сервере я использую:
readerThread :: MyQueue -> Socket -> IO ()
readerThread queue serverSock = do
(connsock, clientaddr) <- accept serverSock
sClose serverSock
putStrLn $ "> connected reader " ++ show clientaddr
talk connsock
sClose connsock
putStrLn $ "> closed reader " ++ show clientaddr
return ()
where
talk conn = do
msg <- recv conn 2048
putStr $ "* get from " ++ show conn ++ "\n"
myQueueWrite queue msg
unless (B.null msg) $ do
talk conn
createInputPort :: ChildLocks -> MyQueue -> AddrInfo -> IO PortNumber
createInputPort children obuffer serverAddr = withSocketsDo $ do
serverSock <- socket AF_INET Stream defaultProtocol
bindSocket serverSock (addrAddress serverAddr)
listen serverSock 1
lock <- newChildLock children
_ <- forkIO $ readerThread obuffer serverSock `finally` endChildLock lock
socketPort serverSock
Y использовать собственную очередь (TCHAN) для связи между читателем сети потоком потребителя и childLocks для ожидания в конце с чем-то вроде waitForChildren children
конструкции, которую я нашелstackoverflow.
ОБНОВЛЕНИЕ: waitForChildren
в сообщении Сравнение потоков Haskell с потоками ядра - мой тест жизнеспособен?