在C#中使用TcpClient或通常连接到套接字,如何首先检查计算机上某个端口是否空闲?
更多信息: 这是我使用的代码:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
在C#中使用TcpClient或通常连接到套接字,如何首先检查计算机上某个端口是否空闲?
更多信息: 这是我使用的代码:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
Answers:
由于您使用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.
netstat -a -b
。请注意,LISTENING
中没有连接GetActiveTcpConnections()
。您还应该签入System.Net.IPEndPoints[]
ipGlobalProperties.GetActiveTcpListeners();
您在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");
}
失败:
通常,每个套接字地址(协议/网络地址/端口)只能使用一种。
设置TCP连接时,四元组(源IP,源端口,目标IP,目标端口)必须唯一-这是为了确保将数据包传递到正确的位置。
服务器端还有一个限制,即只有一个服务器程序可以绑定到传入的端口号(假设一个IP地址;多NIC服务器具有其他功能,但我们无需在此处进行讨论)。
因此,在服务器端,您:
在客户端,通常会更简单一些:
有没有要求,目标IP /端口是唯一的,因为这将导致只有一个人在同一时间能够使用谷歌,这将很好摧毁他们的商业模式。
这意味着您甚至可以执行多会话FTP之类的奇妙操作,因为您设置了多个会话,唯一的区别就是源端口,从而允许您并行下载块。洪流有点不同,因为每个会话的目的地通常是不同的。
而且,经过所有这些麻烦(对不起),对您的特定问题的答案是,您无需指定空闲端口。如果您通过未指定源端口的呼叫连接到服务器,则几乎可以肯定地使用了零,系统将为您提供未使用的端口。
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
...如何首先检查机器上的某个端口是否空闲?
我的意思是其他任何应用程序都没有使用它。如果应用程序正在使用端口,则其他应用程序必须等到它变得免费后才能使用。–阿里
您误解了这里发生的事情。
TcpClient(...)参数包含您要连接的服务器IP和服务器端口。
TcpClient从可用池中选择一个临时本地端口以与服务器通信。由于Winsock层会自动处理本地端口,因此无需检查本地端口的可用性。
如果您无法使用上述代码片段连接到服务器,则问题可能出在其中的一个或多个。(即服务器IP和/或端口错误,远程服务器不可用,等等。)
感谢您的提示。我需要相同的功能,但需要在服务器端检查端口是否正在使用中,因此我将其修改为此代码。
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;
}
-anb
)的应用程序的PID,并且不带任何参数,它显示了外部连接和状态。
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);
}
netstat!这是Windows附带的网络命令行实用程序。它显示所有当前建立的连接和当前正在侦听的所有端口。您可以使用此程序进行检查,但是如果要通过代码执行此操作,请查看System.Net.NetworkInformation命名空间?从2.0开始,这是一个新的命名空间。那里有一些好东西。但是最终,如果您想通过命令netstat获得相同类型的信息,则需要进行P / Invoke调用。
该名称空间包含一堆类,您可以使用这些类来了解有关网络的信息。
我找不到旧的代码,但我想您可以自己编写类似的东西。一个好的开始是检查IP Helper API。用于GetTcpTable WINAPI函数的Google MSDN, 并使用P / Invoke进行枚举,直到获得所需的信息为止。
你说
我的意思是其他任何应用程序都没有使用它。如果应用程序正在使用端口,则其他应用程序必须等到它变得免费后才能使用。
但是,如果有人正在监听某个端口,那么您始终可以连接到该端口,而其他人正在使用它。否则,http端口80会一团糟。
如果你的
c = new TcpClient(ip, port);
失败,那么那里什么也没听。否则,即使其他某些机器/应用程序的ip和端口都打开了套接字,它也会连接。
从可用的端口中,我将排除:
使用以下导入:
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
为了回答在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的评论,我搜索并找到了该端口并对其进行了少许修改。
请注意,从进行检查到尝试进行连接之间的时间窗口可能需要使用某些端口,例如经典的TOCTOU。您为什么不尝试连接?如果失败,则说明该端口不可用。
您不必知道在本地计算机上打开了哪些端口即可连接到某些远程TCP服务(除非您想使用特定的本地端口,但通常情况并非如此)。
每个TCP / IP连接都由4个值标识:远程IP,远程端口号,本地IP,本地端口号,但是您只需知道远程IP和远程端口号即可建立连接。
当您使用创建TCP连接时
TcpClient c; c =新的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.");
}
}
}