[英]Haskell tcp server, fd is too big error
我一直在嘗試為Go客戶端編寫Haskell服務器。 對於Haskell TCP服務器,我只是使用Network.Socket
。 每當我嘗試運行hWaitForInput
時,都會出現此錯誤:
fdReady: fd is too big.
這是服務器代碼-
connHandler :: (Socket, SockAddr) -> IO()
connHandler (sock, _) = do
putStrLn "Starting Handler"
handle <- socketToHandle sock ReadWriteMode
hSetBuffering handle LineBuffering
hPutStrLn handle "Hello Client!"
putStrLn "Waiting for Input"
success <- hWaitForInput handle (1000*10)
putStrLn "Wait done"
if success
then do
putStrLn "Client timed out"
else do
msg <- hGetLine handle
putStrLn msg
hClose handle
Go客戶端正在接收並打印服務器的消息(“ Hello Client!”),但是haskell服務器在打印“ Waiting for Input”后立即拋出錯誤。
你沒有做錯任何事。 您看到的特定錯誤消息僅在Windows上運行的GHC> = 8.0.2時出現,並且表示內部GHC功能fdReady
中的錯誤/限制,他們已嘗試在非Windows體系結構上解決這些問題,但未解決視窗。 (不過,不要嫉妒–非Windows體系結構上的“修復”目前已損壞並崩潰。)嘗試使用較早版本的GHC可能無濟於事–仍然會導致錯誤,但是錯誤消息將有所不同。
這就是問題所在:在Windows上,內部函數fdReady
使用select()
系統調用輪詢套接字的文件描述符,而select
fdReady
將其輪詢的文件描述符限制為某個最大數值。 它看起來像Windows默認這個值是相當低(64),但是可以在編譯時增加(GHC編譯,不幸的是,沒有的時候GHC編譯程序的時間)。
如果添加行:
hShow handle >>= putStrLn
在hWaitForInput
之前,您應該看到為套接字打印了一些調試信息,包括loc=<socket: nnn>
,其中nnn
是文件描述符。 這可以幫助您驗證是否看到了大於64的文件描述符,從而導致了問題。
如果是這種情況,我建議您提交GHC錯誤,以查看是否可以修復它。
作為一種替代方法/解決方法,您可以嘗試在一個線程中讀取一行,在另一個線程中讀取計時器。
putStrLn "Waiting for Input"
msgMVar <- newEmptyMVar
tid <- forkIO $ hGetLine handle >>= putMVar msgMVar
maybeExn <- waitTimeout tid (1000*10)
case maybeExn of
Nothing -> do
killThread tid
putStrLn "Client timed out"
Just (Just _) ->
putStrLn "Exception"
_ -> do
msg <- takeMVar msgMVar
putStrLn msg
hClose handle
但是,這確實具有與您的代碼不同的行為(可能在讀取行中間超時)(即使行未完成,如果可以讀取單個字節,也永遠不會超時)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.