我想检查某个端口是否打开(Haskell)?

时间:2016-08-25 08:02:35

标签: http haskell port ghc

我想检查某个主机上是否有某个端口是打开的。我怎样才能做到这一点?在我打电话给.draw()之后接下来的事情,我怎么才能真正知道端口是否打开?

function dashedBorder(chart, dataset, data, dash) {

    // edit the .draw() function
    chart.config.data.datasets[dataset]._meta[0].data[data].draw = function() {
        chart.chart.ctx.setLineDash(dash);
        Chart.elements.Rectangle.prototype.draw.apply(this, arguments);

        // put the line style back to the default value
        chart.chart.ctx.setLineDash([1,0]);
    }
}

2 个答案:

答案 0 :(得分:2)

如果connectTo返回,则端口打开。否则会抛出像

这样的异常
*** Exception: connect: failed (Connection timed out (WSAETIMEDOUT))

*** Exception: connect: failed (Connection refused (WSAECONNREFUSED))

所以你可以做到

import Network(connectTo, PortID(..), PortNumber(..))
import Control.Exception(try, SomeException)
import System.IO(Handle)

isPortOpen :: String -> PortNumber -> IO Bool
isPortOpen host port = do
  h <- try $ connectTo host (PortNumber port) :: IO (Either SomeException Handle)
  return $ case h of
    Left _ -> False
    Right _ -> True

答案 1 :(得分:1)

这里的主要任务是连接到呼叫connect,并准确捕获主机拒绝连接的情况(而不是主机不存在或无法路由)。

>

使用新的Network.Socket API(而不是已弃用的Socket模块)和unliftio包的解决方案,以确保异步异常处理的安全(您可以使用Control.Exception,将会是less safe):

import           Data.Word (Word8)
import           Foreign.C.Error (Errno(..), eCONNREFUSED)
import           GHC.IO.Exception (IOException(..))
import           Network.Socket (PortNumber, socket, connect, close', Family(AF_INET), SocketType(Stream), SockAddr(SockAddrInet), tupleToHostAddress)
import           UnliftIO.Exception (try, bracket, throwIO)


-- | Checks whether @connect()@ to a given TCPv4 `SockAddr` succeeds or
-- returns `eCONNREFUSED`.
--
-- Rethrows connection exceptions in all other cases (e.g. when the host
-- is unroutable).
isPortOpen :: SockAddr -> IO Bool
isPortOpen sockAddr = do
  bracket (socket AF_INET Stream 6 {- TCP -}) close' $ \sock -> do
    res <- try $ connect sock sockAddr
    case res of
      Right () -> return True
      Left e ->
        if (Errno <$> ioe_errno e) == Just eCONNREFUSED
          then return False
          else throwIO e


-- | Creates a `SockAttr` from host IP and port number.
--
-- Example:
-- > simpleSockAddr (127,0,0,1) 8000
simpleSockAddr :: (Word8, Word8, Word8, Word8) -> PortNumber -> SockAddr
simpleSockAddr addr port = SockAddrInet port (tupleToHostAddress addr)

那么您可以做:

> isPortOpen (simpleSockAddr (127,0,0,1) 8000)
True

this gist中的完整模块。