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

在C#中使用TcpClient或通常连接到套接字如何首先检查我的机器上的某个端口是否可用?

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

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

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

使用IPGlobalProperties对象获取IPGlobalProperties对象的数组,然后可以询问有关端点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. 

你在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"); } 

失败:

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

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

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

所以,在服务器端,你:

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

在客户端,通常会更简单一些:

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

没有要求目标IP /端口是唯一的,因为那样一次只能有一个人能够使用Google,而且这将很好地摧毁他们的商业模式。

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

而且,毕竟这个问题(对不起),对于你的具体问题的答案是你不需要指定一个空闲的端口。 如果你连接到一个没有指定你的源端口的调用的服务器,它几乎肯定会使用零下的覆盖,系统会给你一个未使用的。

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

…我怎样才能首先检查我的机器上的某个端口是否可用?

我的意思是它没有被其他应用程序使用。 如果一个应用程序正在使用一个端口,那么别人不能使用它,直到它变成空闲的。 – 阿里

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

TcpClient(…)参数是您希望连接到的服务器IP和服务器端口。

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

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

感谢您的提示。 我需要相同的function,但在服务器端检查端口是否在使用,所以我修改它到这个代码。

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

谢谢你的答案。 我不得不调整我的用法。 我需要检查一个端口是否正在被侦听,而不是必须激活。 为此我replace了

 TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections(); 

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

我迭代了端点数组,检查我的端口值没有find。

netstat的! 这是一个与Windows一起发布的networking命令行工具。 它显示当前正在build立的连接和当前正在监听的所有端口。 你可以使用这个程序来检查,但是如果你想从代码中查看System.Net.NetworkInformation命名空间呢? 这是从2.0开始的新命名空间。 那里有些好东西。 但最终如果你想获得通过命令netstat可用的相同types的信息,您将需要导致P / Invoke …

更新:System.Net.NetworkInformation

这个命名空间包含了一堆你可以用来解决networking问题的类。

我无法find那些旧的代码,但我想你可以自己写一些类似的东西。 一个好的开始是检查IP助手API 。 Google MSDN的GetTcpTable WINAPI函数,并使用P / Invoke枚举,直到你有你需要的信息。

你说

我的意思是它没有被其他应用程序使用。 如果一个应用程序正在使用一个端口,那么别人不能使用它,直到它变成空闲的。

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

如果你的

  c = new TcpClient(ip, port); 

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

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

但是,这总是会导致竞争状况。

规范的检查方法是尝试在该端口上收听。 如果你得到一个错误,端口没有打开。

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

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

端口可以​​用于监听,但是没有人连接到上述方法将不起作用。

请注意,您进行检查的时间窗口和您尝试进行连接的时间,某些过程可能需要端口 – 古典TOCTOU 。 你为什么不试试连接? 如果失败,那么你知道该端口不可用。

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

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

当你创buildTCP连接使用

 TcpClient c;
 c = new TcpClient(remote_ip,remote_port);

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

  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; } 
 test_connection("ip", port); public void test_connection(String hostname, int portno) { 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) { MessageBox.Show("Port is in use"); } sock.Close(); } catch (System.Net.Sockets.SocketException ex) { if (ex.ErrorCode == 10060) { MessageBox.Show("No connection."); } } } 

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

 IPEndPoint endPoint; int port = 1; while (true) { try { endPoint = new IPEndPoint(IPAddress.Any, port); break; } catch (SocketException) { port++; } }