В C#, как проверить, доступен ли TCP-порт?
17 ответов
так как вы используете TcpClient
, это означает, что вы проверяете открытые TCP-порты. Есть много хороших объектов, доступных в система.Сеть.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.
ты на неправильном конце 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-соединения 4-кортеж (source-ip, source-port, dest-ip, dest-port) должен быть уникальным - это гарантирует, что пакеты доставляются в нужное место.
существует дополнительное ограничение на сервер сторона, что только одна серверная программа может привязываться к входящему номеру порта (при условии, что один IP-адрес; серверы multi-NIC имеют другие полномочия, но нам не нужно обсуждать их здесь).
Итак, в конце сервера, ты:
- создать сокет.
- свяжите этот сокет с портом.
- прослушивает этот порт.
- принимать соединения на этом порту. и может быть несколько подключений (по одному на клиента).
на клиентском конце обычно немного проще:
- создать сокет.
- открываем подключение. Когда клиент открывает соединение, он указывает ip-адрес и порт сервер. Это can укажите его исходный порт, но обычно использует ноль, что приводит к тому, что система автоматически назначает ему свободный порт.
здесь нет требование, чтобы IP/порт назначения был уникальным, так как это приведет к тому, что только один человек одновременно сможет использовать Google, и это довольно хорошо разрушит их бизнес-модель.
Это означает, что вы даже можете делать такие удивительные вещи, как многосессионный FTP, так как вы настройте несколько сеансов, где единственным отличием является исходный порт, позволяющий загружать фрагменты параллельно. Торренты немного отличаются тем, что назначение каждого сеанса обычно отличается.
и, после всего этого болтовня (извините), ответ на ваш конкретный вопрос заключается в том, что вам не нужно указать Свободный порт. Если вы подключаетесь к серверу с вызовом, который не указывает ваш исходный порт, он почти наверняка будет использовать ноль под обложками и система даст вам неиспользуемый.
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
...как я могу сначала проверить, свободен ли определенный порт на моей машине?
Я имею в виду, что он не используется другим приложением. Если приложение использует порт другие не могут использовать его, пока он не становится свободным. - Али!--3-->
вы не поняли, что здесь происходит.
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;
}
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);
}
спасибо за ответ jro. Я должен был настроить его для моего использования. Мне нужно было проверить, прослушивается ли порт, а не обязательно активен. Для этого Я заменил
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
С
IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.
Я повторил массив конечных точек, проверяя, что мое значение порта не найдено.
команды netstat! Это утилита командной строки сети, которая поставляется с windows. Он показывает все текущие установленные соединения и все порты, которые в настоящее время прослушиваются. Вы можете использовать эту программу для проверки, но если вы хотите сделать это из кода, посмотрите в систему.Сеть.Пространство имен NetworkInformation? Это новое пространство имен с 2.0. Там есть кое-что вкусненькое. Но в конце концов, если вы хотите получить такую же информацию, которая доступна через команду netstat вам потребуется результат P / Invoke...
Обновление Системы.Чистая.Сведений о сети
Это пространство имен содержит множество классов, которые вы можете использовать для выяснения дела о сети.
Я не смог найти этот старый код, но я думаю, что вы можете написать что-то подобное сами. Хорошее начало, чтобы проверить IP Helper API. Google MSDN для GetTcpTable функция WINAPI и используйте P / Invoke для перечисления, пока у вас нет информации, которую вы необходимость.
скажете вы
Я имею в виду, что это не используется другое приложение. Если приложение использует порт, который другие не могут использовать пока она не станет свободной.
но вы всегда можете подключиться к порту, пока другие используют его, если что-то слушает там. В противном случае HTTP-порт 80 будет бардак.
Если
c = new TcpClient(ip, port);
не удается, тогда ничего не слушает там. В противном случае он подключится, даже если какой-то другой машина / приложение имеет сокет, открытый для этого ip и порта.
Если я не очень ошибаюсь, вы можете использовать систему.Сеть.что бы проверить.
тем не менее, это всегда будет иметь гоночное состояние.
канонический способ проверки-попытаться прослушать этот порт. Если вы получите сообщение об ошибке, порт не был открыт.
Я думаю это часть того, почему bind () и listen () являются двумя отдельными системными вызовами.
ipGlobalProperties.GetActiveTcpConnections()
не возвращает соединения в состоянии Listen.
порт может использоваться для прослушивания, но без подключения к нему описанный выше метод не будет работать.
имейте в виду, что окно времени между проверкой и моментом, когда вы пытаетесь установить соединение, какой - то процесс может занять Порт-классический TOCTOU. Почему бы тебе просто не попробовать подключить? Если это не удается, вы знаете, что порт недоступен.
вам не нужно знать, какие порты открыты на вашем локальном компьютере для подключения к какой-либо удаленной службе TCP (если вы не хотите использовать определенный локальный порт, но обычно это не так).
каждое соединение TCP / IP определяется 4 значениями: удаленный IP, номер удаленного порта, локальный IP, номер локального порта, но вам нужно только знать удаленный IP и номер удаленного порта для установления соединения.
при создании tcp-соединения с помощью
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.");
}
}
}
из доступных портов я бы исключил:
- активные 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
попробуйте это, в моем случае номер порта для созданного объекта был недоступен, поэтому я придумал это
IPEndPoint endPoint;
int port = 1;
while (true)
{
try
{
endPoint = new IPEndPoint(IPAddress.Any, port);
break;
}
catch (SocketException)
{
port++;
}
}