32

我似乎找不到任何可以告诉我路由器中的端口是否打开的信息。这甚至可能吗?

我现在拥有的代码似乎并没有真正起作用......

private void ScanPort()
{
    string hostname = "localhost";
    int portno = 9081;
    IPAddress ipa = (IPAddress) Dns.GetHostAddresses(hostname)[0];
    try
    {
        System.Net.Sockets.Socket sock =
                new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork,
                                              System.Net.Sockets.SocketType.Stream,
                                              System.Net.Sockets.ProtocolType.Tcp);
        sock.Connect(ipa, portno);
        if (sock.Connected == true) // Port is in use and connection is successful
            MessageBox.Show("Port is Closed");
        sock.Close();
    }
    catch (System.Net.Sockets.SocketException ex)
    {
        if (ex.ErrorCode == 10061) // Port is unused and could not establish connection 
            MessageBox.Show("Port is Open!");
        else
            MessageBox.Show(ex.Message);
    }
}
4

10 回答 10

52

尝试这个:

using(TcpClient tcpClient = new TcpClient())
{
    try {
        tcpClient.Connect("127.0.0.1", 9081);
        Console.WriteLine("Port open");
    } catch (Exception) {
        Console.WriteLine("Port closed");
    }
}

您可能应该将 127.0.0.1 更改为 192.168.0.1 或任何您的路由器的 IP 地址。

于 2012-08-07T00:09:58.513 回答
34

一个更好的解决方案,您甚至可以指定超时:

using System;
using System.Net.Sockets;

// ...

bool IsPortOpen(string host, int port, TimeSpan timeout)
{
    try
    {
        using(var client = new TcpClient())
        {
            var result = client.BeginConnect(host, port, null, null);
            var success = result.AsyncWaitHandle.WaitOne(timeout);
            client.EndConnect(result);
            return success;
        }
    }
    catch
    {
        return false;
    }
}

而且,在 F# 中:

open System
open System.Net.Sockets

let isPortOpen (host: string) (port: int) (timeout: TimeSpan): bool =
    try
        use client = new TcpClient()
        let result = client.BeginConnect(host, port, null, null)
        let success = result.AsyncWaitHandle.WaitOne timeout
        client.EndConnect result
        success
    with
    | _ -> false

let available = isPortOpen "stackoverflow.com" 80 (TimeSpan.FromSeconds 10.)
printf "Is stackoverflow available? %b" available
于 2016-07-08T02:39:07.147 回答
4

没有办法知道该端口是否在您的路由器中转发,除非有程序在该端口上侦听。

正如您在克林顿的回答中看到的那样,正在使用的 .Net 类是 TcpClient ,这是因为您正在使用 TCP 套接字进行连接。这就是操作系统建立连接的方式:使用套接字。但是,路由器只是将数据包(OSI 模型的第 3 层)转发进出。在您的情况下,您的路由器正在执行的操作称为:NAT。它是一个由一个或多个私有 IP 共享的公共 IP。这就是您进行端口转发的原因。

数据包的路径中可能有很多路由器,你永远不会知道发生了什么。

假设您正在以传统方式发送一封信。也许您可以在信中写下收件人必须回答,以检查他/她是否在那里(您和收件人是插座)。如果您收到答复,您将确定他/她在那里,但如果您没有收到任何东西,您不知道邮递员(在您的情况下是路由器)是否忘记递送信件,或者收件人没有回答。您也永远不会知道邮递员是否要求朋友送出那封信。此外,邮递员不会打开这封信以知道他/她可能会回复,因为您正在等待回复。您可能要做的就是等待一段时间才能收到答案。如果你在那段时间没有收到任何东西,你会认为收件人不在你寄信的地方。那是一个“超时”。

我看到一个提到 nmap 软件的答案。它真的是一个非常好的和复杂的软,但我认为它会以同样的方式工作。如果该端口中没有应用程序侦听,则无法知道它是否打开。

请让我知道我是否清楚。

于 2017-02-27T16:26:36.090 回答
3

如果您要连接到环回适配器——localhost或者127.0.0.1没有像 127.0.0.1 这样的地方!),那么您不太可能连接到路由器。操作系统足够聪明,可以识别它是一个特殊地址。如果您实际指定机器的“真实”IP 地址,不知道这是否也适用。

另请参阅此问题:Microsoft Loopback Adapter 的用途是什么?

另请注意,运行traceroute localhosttracert localhost在 Windows 中)表明所涉及的唯一网络节点是您自己的机器。路由器从不涉及。

于 2012-08-07T00:13:19.500 回答
2

除了 BeginConnect,您还可以使用 ConnectAsync(我认为是在 .NET Framework 4.5 中添加的?)。

TcpClient client = null;

try {
    client = new TcpClient();
    var task = client.ConnectAsync(host, port);
    if (task.Wait(timeout)) {//if fails within timeout, task.Wait still returns true.
        if (client.Connected) {
            // port reachable
        }
        else
            // connection refused probably
    }
    else
        // timed out
}
catch (Exception ex) {
    // connection failed
}
finally {
    client.Close();
}

完整的项目在这里,因为 paping 拒绝运行,而且我找不到另一个我喜欢的“ping host:port”工具。

于 2020-09-11T03:57:03.913 回答
1

无法从 LAN 内部测试路由器上的端口转发,您需要从 WAN(互联网)端连接以查看端口转发是否工作。

一些互联网站点提供检查端口是否打开的服务:

什么是我的 IP 端口扫描仪

GRC | 盾牌!

如果您想检查自己的代码,则需要确保 TCP/IP 连接通过外部代理重新路由或设置隧道。这与您的代码无关,它是基本的网络 101。

于 2014-01-13T09:04:51.870 回答
1
public static bool PortInUse(int  port)
{
    bool inUse = false;

    IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
    IPEndPoint [] ipEndPoints = ipProperties.GetActiveTcpListeners();


    foreach(IPEndPoint endPoint in ipEndPoints)
    {
        if(endPoint.Port == port)
        {
            inUse = true;
            break;
        }
    }


    return  inUse;
}
于 2018-05-29T05:46:53.603 回答
0

对我来说,在与端口的连接可用或经过一定次数的重试之前,我需要一些阻塞。所以,我想出了这段代码:

public bool IsPortOpen(string host, int port, int timeout, int retry)
{
    var retryCount = 0;
    while (retryCount < retry)
    {
        if (retryCount > 0)
            Thread.Sleep(timeout);

        try
        {
            using (var client = new TcpClient())
            {
                var result = client.BeginConnect(host, port, null, null);
                var success = result.AsyncWaitHandle.WaitOne(timeout);
                if (success)
                    return true;

                client.EndConnect(result);
            }
        }
        catch
        {
            // ignored
        }
        finally { retryCount++; }
    }

    return false;
}

希望这可以帮助!

于 2018-05-18T14:18:19.073 回答
-1
public string GetAvailablePort()
        {int startingPort=1000;
            string portnumberinformation = string.Empty;
            IPEndPoint[] endPoints;
            List<int> portArray = new List<int>();
            IPGlobalPr`enter code here`operties properties = IPGlobalProperties.GetIPGlobalProperties();`enter code here`


            //getting active tcp listners 
            endPoints = properties.GetActiveTcpListeners();
            portArray.AddRange(from n in endPoints
                               where n.Port >= startingPort
                               select n.Port);    

            portArray.Sort();

            for (int i = 0; i < portArray.Count; i++)
            {
                if (check condition)
                {
                    do somting
                }
            }

            return portnumberinformation;
        }
于 2019-04-26T10:21:58.940 回答
-4

如果是路由器,是通过在线服务检查它的最简单方法,例如

您也可以尝试使用Telenet来检查端口是否可以访问

telenet [ip-address] [port] 
于 2019-11-08T05:50:34.120 回答