我想检查某个主机上是否有某个端口是打开的。我怎样才能做到这一点?在我打电话给.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]);
}
}
答案 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中的完整模块。