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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/570098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:38:27  来源:igfitidea点击:

In C#, how to check if a TCP port is available?

c#.nettcptcpclient

提问by Ali

In C# to use a TcpClient or generally to connect to a socket how can I first check if a certain port is free on my machine?

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

more info:This is the code I use:

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

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

采纳答案by jro

Since you're using a TcpClient, that means you're checking open TCP ports. There are lots of good objects available in the System.Net.NetworkInformationnamespace.

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

Use the IPGlobalPropertiesobject to get to an array of TcpConnectionInformationobjects, which you can then interrogate about endpoint IP and port.

使用该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.

回答by John Leidegren

netstat! That's a network command line utility which ships with windows. It shows all current established connections and all ports currently being listened to. You can use this program to check, but if you want to do this from code look into the System.Net.NetworkInformation namespace? It's a new namespace as of 2.0. There's some goodies there. But eventually if you wanna get the same kind of information that's available through the command netstat you'll need to result to P/Invoke...

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

Update: System.Net.NetworkInformation

更新:System.Net.NetworkInformation

That namespace contains a bunch of classes you can use for figuring out things about the network.

该命名空间包含一堆类,您可以使用它们来了解有关网络的信息。

I wasn't able to find that old pice of code but I think you can write something similar yourself. A good start is to check out the IP Helper API. Google MSDN for the GetTcpTableWINAPI function and use P/Invoke to enumerate until you have the information you need.

我无法找到那段旧代码,但我认为您可以自己编写类似的东西。一个好的开始是查看IP Helper API。谷歌 MSDN 获取 GetTcpTableWINAPI 函数并使用 P/Invoke 进行枚举,直到您获得所需的信息。

回答by Learning

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

回答by Moose

You say

你说

I mean that it is not in use by any other application. If an application is using a port others can't use it until it becomes free.

我的意思是它没有被任何其他应用程序使用。如果一个应用程序正在使用一个端口,其他人在它变得免费之前不能使用它。

But you can always connect to a port while others are using it if something's listening there. Otherwise, http port 80 would be a mess.

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

If your

如果你的

   c = new TcpClient(ip, port);

fails, then nothing's listening there. Otherwise, it will connect, even if some other machine/application has a socket open to that ip and port.

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

回答by Hans Passant

You're on the wrong end of the Intertube. It is the server that can have only one particular port open. Some code:

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

Fails with:

失败:

Only one usage of each socket address (protocol/network address/port) is normally permitted.

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

回答by Hans Passant

ipGlobalProperties.GetActiveTcpConnections()doesn't return connections in Listen State.

ipGlobalProperties.GetActiveTcpConnections()不返回处于侦听状态的连接。

Port can be used for listening, but with no one connected to it the method described above will not work.

端口可用于侦听,但没有人连接到它上面描述的方法将不起作用。

回答by Indy9000

TcpClient c;

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

...how can I first check if a certain port is free on my machine?

I mean that it is not in use by any other application. If an application is using a port others can't use it until it becomes free. – Ali

...我如何首先检查我的机器上某个端口是否空闲?

我的意思是它没有被任何其他应用程序使用。如果一个应用程序正在使用一个端口,其他人在它变得免费之前不能使用它。– 阿里

You have misunderstood what's happening here.

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

TcpClient(...) parameters are of server ip and server port you wish to connect to.

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

The TcpClient selects a transient local port from the available pool to communicate to the server. There's no need to check for the availability of the local port as it is automatically handled by the winsock layer.

TcpClient 从可用池中选择一个临时本地端口来与服务器通信。无需检查本地端口的可用性,因为它由 winsock 层自动处理。

In case you can't connect to the server using the above code fragment, the problem could be one or more of several. (i.e. server ip and/or port is wrong, remote server not available, etc..)

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

回答by paxdiablo

When you set up a TCP connection, the 4-tuple (source-ip, source-port, dest-ip, dest-port) has to be unique - this is to ensure packets are delivered to the right place.

当您建立 TCP 连接时,4 元组(源 IP、源端口、目标 IP、目标端口)必须是唯一的 - 这是为了确保数据包被传送到正确的位置。

There is a further restriction on the serverside that only one server program can bind to an incoming port number (assuming one IP address; multi-NIC servers have other powers but we don't need to discuss them here).

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

So, at the server end, you:

因此,在服务器端,您:

  • create a socket.
  • bind that socket to a port.
  • listen on that port.
  • accept connections on that port. and there can be multiple connections coming in (one per client).
  • 创建一个套接字。
  • 将该套接字绑定到端口。
  • 监听那个端口。
  • 接受该端口上的连接。并且可以有多个连接进入(每个客户端一个)。

On the client end, it's usually a little simpler:

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

  • create a socket.
  • open the connection. When a client opens the connection, it specifies the ip address and port of the server. It canspecify its source port but usually uses zero which results in the system assigning it a free port automatically.
  • 创建一个套接字。
  • 打开连接。当客户端打开连接时,它指定服务器的 ip 地址和端口。它可以指定其源端口,但通常使用零,这会导致系统自动为其分配一个空闲端口。

There is norequirement that the destination IP/port be unique since that would result in only one person at a time being able to use Google, and that would pretty well destroy their business model.

没有要求,目标IP /端口是唯一的,因为这将导致只有一个人在同一时间能够使用谷歌,这将很好摧毁他们的商业模式。

This means you can even do such wondrous things as multi-session FTP since you set up multiple sessions where the only difference is your source port, allowing you to download chunks in parallel. Torrents are a little different in that the destination of each session is usually different.

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

And, after all that waffling (sorry), the answer to your specific question is that you don't need to specify a free port. If you're connecting to a server with a call that doesn't specify your source port, it'll almost certainly be using zero under the covers and the system will give you an unused one.

而且,在胡说八道之后(抱歉),您的具体问题的答案是您不需要指定自由端口。如果您通过未指定源端口的调用连接到服务器,则几乎肯定会在幕后使用零,系统会给您一个未使用的。

回答by ya23

Be aware the time window between you make check and the moment you try to make connection some process may take the port - classical TOCTOU. Why don't you just try to connect? If it fails then you know the port is not available.

请注意您进行检查和您尝试建立连接之间的时间窗口,某些进程可能会采用端口 - 经典的TOCTOU。你为什么不尝试连接?如果失败,则您知道该端口不可用。

回答by Micha? Piaskowski

You don't have to know what ports are open on your local machine to connect to some remote TCP service (unless you want to use a specific local port, but usually that is not the case).

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

Every TCP/IP connection is identified by 4 values: remote IP, remote port number, local IP, local port number, but you only need to know remote IP and remote port number to establish a connection.

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

When you create tcp connection using

当您使用创建 tcp 连接时

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

Your system will automatically assign one of many free local port numbers to your connection. You don't need to do anything. You might also want to check if a remote port is open. but there is no better way to do that than just trying to connect to it.

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