在C#中,如何检查TCP端口是否可用?

时间:2009-02-20 15:53:38

标签: c# .net tcp tcpclient

在C#中使用TcpClient或通常连接到套接字我怎样才能首先检查我的机器上某个端口是否空闲?

更多信息: 这是我使用的代码:

TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);

19 个答案:

答案 0 :(得分:202)

由于您使用的是TcpClient,这意味着您正在检查打开的TCP端口。 System.Net.NetworkInformation命名空间中有许多好的对象。

使用IPGlobalProperties对象访问TcpConnectionInformation个对象数组,然后可以查询端点IP和端口。


 int port = 456; //<--- This is your value
 bool isAvailable = true;

 // Evaluate current system tcp connections. This is the same information provided
 // by the netstat command line application, just in .Net strongly-typed object
 // form.  We will look through the list, and if our port we would like to use
 // in our TcpClient is occupied, we will set isAvailable to false.
 IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
 TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

 foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
 {
   if (tcpi.LocalEndPoint.Port==port)
   {
     isAvailable = false;
     break;
   }
 }

 // At this point, if isAvailable is true, we can proceed accordingly.

答案 1 :(得分:40)

你在Intertube的错误一端。服务器只能打开一个特定端口。一些代码:

  IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
  try {
    TcpListener tcpListener = new TcpListener(ipAddress, 666);
    tcpListener.Start();
  }
  catch (SocketException ex) {
    MessageBox.Show(ex.Message, "kaboom");
  }

失败:

  

通常只允许使用每个套接字地址(协议/网络地址/端口)。

答案 2 :(得分:19)

设置TCP连接时,4元组(source-ip,source-port,dest-ip,dest-port)必须是唯一的 - 这是为了确保数据包被传送到正确的位置。 / p>

服务器方面还有一个限制,即只有一个服务器程序可以绑定到传入端口号(假设一个IP地址;多个NIC服务器具有其他权限,但我们不需要在这里讨论它们。)

所以,在服务器端,你:

  • 创建一个套接字。
  • 将该套接字绑定到端口。
  • 听那个港口。
  • 接受该端口上的连接。 并且可以有多个连接(每个客户端一个)。

在客户端,它通常有点简单:

  • 创建一个套接字。
  • 打开连接。 当客户端打开连接时,它指定服务器的IP地址和端口。 可以指定其源端口,但通常使用零,这会导致系统自动为其分配一个空闲端口。

没有要求目标IP /端口是唯一的,因为这样一次只能有一个人能够使用Google,这很可能会破坏他们的商业模式。< / p>

这意味着您甚至可以执行多会话FTP这样的奇妙事情,因为您设置了多个会话,其中唯一的区别是您的源端口,允许您并行下载块。 Torrent有点不同,因为每个会话的目的地通常是不同的。

而且,在所有这些胡扯(抱歉)之后,您的具体问题的答案是您不需要指定自由端口。如果您使用未指定源端口的呼叫连接到服务器,那么它几乎肯定会在封面下使用零,系统将为您提供未使用的端口。

答案 3 :(得分:15)

TcpClient c;

//I want to check here if port is free.
c = new TcpClient(ip, port);
  

...我怎样才能首先检查我的机器上某个端口是否空闲?

     

我的意思是它没有被任何其他应用程序使用。   如果某个应用程序正在使用某个端口,则其他应用程序无法使用它 - 阿里

你误解了这里发生的事情。

TcpClient(...)参数是您要连接的服务器IP和服务器端口。

TcpClient从可用池中选择一个临时本地端口与服务器进行通信。没有必要检查本地端口的可用性,因为它是由winsock层自动处理的。

如果您无法使用上述代码片段连接到服务器,则问题可能是多个问题中的一个或多个。 (即服务器IP和/或端口错误,远程服务器不可用等等。)

答案 4 :(得分:14)

感谢您的提示。我需要相同的功能,但在服务器端检查端口是否正在使用,所以我将其修改为此代码。

 private bool CheckAvailableServerPort(int port) {
    LOG.InfoFormat("Checking Port {0}", port);
    bool isAvailable = true;

    // Evaluate current system tcp connections. This is the same information provided
    // by the netstat command line application, just in .Net strongly-typed object
    // form.  We will look through the list, and if our port we would like to use
    // in our TcpClient is occupied, we will set isAvailable to false.
    IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
    IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();

    foreach (IPEndPoint endpoint in tcpConnInfoArray) {
        if (endpoint.Port == port) {
            isAvailable = false;
            break;
        }
    }

    LOG.InfoFormat("Port {0} available = {1}", port, isAvailable);

    return isAvailable;
}

答案 5 :(得分:6)

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);
}

答案 6 :(得分:6)

感谢答案jro。我不得不调整它以供我使用。我需要检查是否正在监听端口,而不是必须激活。为此,我替换了

TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.  

我迭代了端点数组,检查我的端口值是否找不到。

答案 7 :(得分:3)

的netstat!这是一个随Windows一起提供的网络命令行实用程序。它显示所有当前建立的连接和当前正在侦听的所有端口。您可以使用此程序进行检查,但是如果您想从代码中执行此操作,请查看System.Net.NetworkInformation命名空间?它是2.0的新命名空间。那里有一些好吃的东西。但最终如果你想获得通过netstat命令获得的相同类型的信息,你需要得到P / Invoke ......

更新:System.Net.NetworkInformation

该命名空间包含许多可用于弄清网络内容的类。

我无法找到那些旧的代码,但我认为你可以自己编写类似的东西。一个好的开始是查看IP Helper API。用于GetTcpTable WINAPI功能的Google MSDN,并使用P / Invoke进行枚举,直到您获得所需信息为止。

答案 8 :(得分:2)

你说

  

我的意思是它没有被任何人使用   其他申请。如果申请   正在使用其他人无法使用的端口   直到它变得自由。

但是你可以随时连接到一个端口,而其他人正在使用它,如果有人在那里听的话。否则,http端口80将是一团糟。

如果你的

   c = new TcpClient(ip, port);

失败了,然后没有人在那里听。否则,它将连接,即使某些其他机器/应用程序有一个打开该ip和端口的套接字。

答案 9 :(得分:2)

ipGlobalProperties.GetActiveTcpConnections()不会在侦听状态中返回连接。

端口可以用于收听,但没有人连接到它,上述方法将无效。

答案 10 :(得分:2)

如果我没有弄错,你可以使用System.Network.whatever来检查。

然而,这将始终招致竞争条件。

规范的检查方法是尝试侦听该端口。如果您收到端口未打开的错误。

认为这是为什么bind()和listen()是两个独立的系统调用的一部分。

答案 11 :(得分:1)

您不必知道本地计算机上打开哪些端口以连接到某些远程TCP服务(除非您想使用特定的本地端口,但通常情况并非如此)。

每个TCP / IP连接由4个值标识:远程IP,远程端口号,本地IP,本地端口号,但您只需要知道远程IP和远程端口号即可建立连接。

使用

创建tcp连接时
TcpClient c;
c = new TcpClient(remote_ip, remote_port);

您的系统会自动为您的连接分配许多免费本地端口号之一。你不需要做任何事情。 您可能还想检查远程端口是否已打开。但没有比仅仅尝试连接它更好的方法了。

答案 12 :(得分:1)

从可用端口中,我将排除:

  • 活动TCP连接
  • 活动TCP侦听器
  • 活动UDP侦听器

具有以下导入:

using System.Net.NetworkInformation;

您可以使用以下功能来检查端口是否可用:

private bool isPortAvalaible(int myPort)
{
    var avalaiblePorts = new List<int>();
    var properties = IPGlobalProperties.GetIPGlobalProperties();

    // Active connections
    var connections = properties.GetActiveTcpConnections();
    avalaiblePorts.AddRange(connections);

    // Active tcp listners
    var endPointsTcp = properties.GetActiveTcpListeners();
    avalaiblePorts.AddRange(endPointsTcp);

    // Active udp listeners
    var endPointsUdp = properties.GetActiveUdpListeners();
    avalaiblePorts.AddRange(endPointsUdp);

    foreach (int p in avalaiblePorts){
        if (p == myPort) return false;
    }
    return true;
}

我为使用 VB.NET 的用户提供了类似的功能:

Imports System.Net.NetworkInformation
Private Function isPortAvalaible(ByVal myPort As Integer) As Boolean
  Dim props As IPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties()

  ' ignore active connections
  Dim tcpConnInfoArray() As TcpConnectionInformation = props.GetActiveTcpConnections()
  For Each tcpi As Net.NetworkInformation.TcpConnectionInformation In tcpConnInfoArray
    If tcpi.LocalEndPoint.Port = myPort Then
      Return False
    End If
  Next tcpi

  ' ignore active TCP listeners
  Dim activeTcpListeners() As Net.IPEndPoint = props.GetActiveTcpListeners
  For Each tcpListener As Net.IPEndPoint In activeTcpListeners
    If tcpListener.Port = myPort Then
      Return False
    End If
  Next tcpListener

  ' ignore active UPD listeners
  Dim activeUdpListeners() As Net.IPEndPoint = props.GetActiveUdpListeners
  For Each udpListener As Net.IPEndPoint In activeUdpListeners
    If udpListener.Port = myPort Then
      Return False
    End If
  Next udpListener

  Return True
End Function

答案 13 :(得分:1)

    public static bool TestOpenPort(int Port)
    {
        var tcpListener = default(TcpListener);

        try
        {
            var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];

            tcpListener = new TcpListener(ipAddress, Port);
            tcpListener.Start();

            return true;
        }
        catch (SocketException)
        {
        }
        finally
        {
            if (tcpListener != null)
                tcpListener.Stop();
        }

        return false;
    }

答案 14 :(得分:1)

请注意您进行检查之间的时间窗口以及尝试建立连接时的某个过程可能需要端口 - 经典TOCTOU。你为什么不尝试连接?如果失败,则表示端口不可用。

答案 15 :(得分:0)

label

答案 16 :(得分:0)

检查错误代码10048

try
{
    TcpListener tcpListener = new TcpListener(ipAddress, portNumber);
    tcpListener.Start();
}
catch(SocketException ex)
{
    if(ex.ErrorCode == 10048)
    {
        MessageBox.Show("Port " + portNumber + " is currently in use.");
    }
    return;
}

答案 17 :(得分:0)

要回答在dotnet core 3.1中找到可用端口的确切问题(这是我在单元测试中需要的端口),我想到了

public static int GetAvailablePort(IPAddress ip) {
        TcpListener l = new TcpListener(ip, 0);
        l.Start();
        int port = ((IPEndPoint)l.LocalEndpoint).Port;
        l.Stop();
        Log.Info($"Available port found: {port}");
        return port;
    }

注意:基于@ user207421关于端口0的评论,我搜索并发现this并对其进行了少许修改。

答案 18 :(得分:-1)

尝试这个,在我的情况下,创建的对象的端口号不可用,所以我想出了这个

{{1}}