Как устранить это исключение: threadWait: неверный аргумент (неверный дескриптор файла) execption [haskell]? - PullRequest
0 голосов
/ 15 января 2020

Я пытаюсь создать клиент-серверную программу, используя сетевую (версия 3.1.1.1) библиотеку Haskell, но при попытке установить sh соединение от клиента к серверу я получаю это исключение *** Исключение: threadWait: неверный аргумент (неверный дескриптор файла) и не знаю, как решить эту проблему.

код:

module PeerToPeer where

import Control.Concurrent (forkFinally)
import qualified Control.Exception as E
import Control.Monad (unless, forever, void)
import qualified Data.ByteString as S
import Network.Socket
import Network.Socket.ByteString (recv, sendAll)
import qualified Data.ByteString.Char8 as C


runServer :: Maybe HostName -> ServiceName -> (Socket -> IO ()) -> IO ()
runServer mhost port process  = withSocketsDo $ do
    addr <- resolveAddr
    E.bracket (open addr) close loop
        where
          resolveAddr = do
              let hints = defaultHints { addrFlags = [AI_PASSIVE], addrSocketType = Stream }
              head <$> getAddrInfo (Just hints) mhost (Just port)

          open addr = do
              sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
              setSocketOption sock ReuseAddr 1
              withFdSocket sock $ setCloseOnExecIfNeeded
              bind sock $ addrAddress addr
              listen sock 1024
              return sock

          loop sock = forever $ do
              (clientSocket, clientAddr) <- accept sock
              putStrLn "Connection Established"
              forkFinally (process sock) (const $ gracefulClose sock 5000)


peerHandler sock = do
    msg <- recv sock 1024
    putStrLn ("Incoming :" ++ (show msg))


runClient :: HostName -> ServiceName -> (Socket -> IO a) -> IO a
runClient host port client = withSocketsDo $ do
    addr <- resolve
    E.bracket (open addr) close client

      where
        resolve = do
            let hints =  defaultHints {addrSocketType = Stream}
            head <$> getAddrInfo (Just hints) (Just host) (Just port)

        open addr = do
            sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
            connect sock $ addrAddress addr
            return sock


peerComm sock = do
    sendAll sock (C.pack "Hello, world!")

Пробовал:

*Server> runServer Nothing "3000" peerHandler 
Connection Established
*** Exception: threadWait: invalid argument (Bad file descriptor)
*Client> runClient "127.0.0.1" "3000" peerComm
...