В C# как проверить, если TCP-порт доступен?



В C# для использования TcpClient или вообще для подключения к сокету как я могу сначала проверить, свободен ли определенный порт на моей машине?



подробнее:
Это код, который я использую:



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

17 ответов:

так как вы используете 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.

ты на неправильном конце 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-адрес; серверы с несколькими сетями имеют другие полномочия, но нам не нужно обсуждать их здесь).

Итак, в конце сервера, ты:

  • создать сокет.
  • привязать сокет к порту.
  • слушайте на этом порту.
  • принять соединения на этом порту. и может быть несколько подключений (по одному на клиента).

на клиентском конце, как правило, немного проще:

  • создать сокет.
  • открываем подключение. Когда клиент открывает соединение, он указывает ip-адрес и порт сервер. Это можете укажите его исходный порт, но обычно использует ноль, что приводит к тому, что система автоматически назначает ему свободный порт.

здесь нет требование, чтобы IP/порт назначения был уникальным, поскольку это приведет к тому, что только один человек одновременно сможет использовать Google, и это довольно хорошо разрушит их бизнес-модель.

Это означает, что вы можете даже делать такие удивительные вещи, как многосессионный 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;
}
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. Он показывает все текущие установленные соединения и все порты, которые в настоящее время прослушиваются. Вы можете использовать эту программу для проверки, но если вы хотите сделать это из кода, посмотрите в пространство имен System.Net.NetworkInformation? Это новое пространство имен с версии 2.0. Там есть кое-какие вкусности. Но в конце концов, если вы хотите получить такую же информацию, которая доступна через команду netstat вам потребуется результат P / Invoke...

Обновление: System. Net. NetworkInformation

Это пространство имен содержит кучу классов, которые можно использовать для выяснения вещей о сети.

Я не смог найти этот старый кусок кода, но я думаю, что вы можете написать что-то подобное самостоятельно. Хорошее начало, чтобы проверить 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++;
    }
}

Comments

    Ничего не найдено.