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

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

Дополнительная информация: Это код, который я использую:

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

Ответ 1

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

Ответ 2

Вы на неправильном конце 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");
  }

Сбой:

Обычно разрешается использование только одного адреса сокета (протокола/сетевого адреса/порта).

Ответ 3

При настройке TCP-соединения 4-кортеж (source-ip, source-port, dest-ip, dest-port) должен быть уникальным - это значит, что пакеты доставлены в нужное место.

На стороне сервера есть еще одно ограничение: только одна серверная программа может привязываться к номеру входящего порта (при условии, что один IP-адрес, серверы с несколькими NIC имеют другие полномочия, но здесь их не нужно обсуждать).

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

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

На стороне клиента это обычно немного проще:

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

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

Это означает, что вы можете даже делать такие чудесные вещи, как многосеансовый FTP, поскольку вы настраиваете несколько сеансов, где единственное различие - ваш исходный порт, позволяющий параллельно загружать куски. Торренты немного отличаются друг от друга тем, что назначение каждой сессии обычно отличается.

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

Ответ 4

TcpClient c;

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

... как я могу сначала проверить, свободен ли какой-либо порт на моей машине?

Я имею в виду, что он не используется никаким другим приложением. Если приложение использует порт, другие не могут использовать его, пока он не станет свободным. - Али

Вы неправильно поняли, что происходит здесь.

Параметры TcpClient (...) относятся к серверу ip и серверному порту, к которому вы хотите подключиться.

TcpClient выбирает переходный локальный порт из доступного пула для связи с сервером. Нет необходимости проверять наличие локального порта, поскольку он автоматически обрабатывается уровнем winsock.

Если вы не можете подключиться к серверу с использованием вышеуказанного фрагмента кода, проблема может быть одной или несколькими из нескольких. (то есть сервер ip и/или порт ошибочен, удаленный сервер недоступен и т.д.)

Ответ 5

Спасибо за этот совет. Мне нужна была такая же функциональность, но на стороне сервера, чтобы проверить, используется ли порт, поэтому я изменил его на этот код.

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

Ответ 6

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

Ответ 7

спасибо за ответ jro. Я должен был настроить его для моего использования. Мне нужно было проверить, прослушивается ли порт, и не обязательно активен. Для этого я заменил

TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

с

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

Я повторил массив конечных точек, проверяя, что значение моего порта не найдено.

Ответ 8

NetStat! Это сетевая утилита командной строки, которая поставляется с окнами. Он показывает все текущие установленные соединения и все порты, которые в настоящее время прослушиваются. Вы можете использовать эту программу для проверки, но если вы хотите сделать это из кода, посмотрите в пространство имен System.Net.NetworkInformation? Это новое пространство имен с 2.0. Там есть некоторые лакомства. Но в конце концов, если вы хотите получить такую ​​же информацию, которая доступна через командную команду netstat, вам нужно будет выполнить P/Invoke...

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

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

Мне не удалось найти этот старый код, но я думаю, что вы можете написать что-то подобное себе. Хорошим началом является проверка IP Helper API. Google MSDN для функции GetTcpTable WINAPI и использовать P/Invoke для перечисления, пока у вас не будет необходимой информации.

Ответ 9

Вы говорите

Я имею в виду, что он не используется никакими другое приложение. Если приложение использует другой порт, который не может его использовать пока он не станет свободным.

Но вы всегда можете подключиться к порту, в то время как другие его используют, если что-то слушает. В противном случае http-порт 80 будет беспорядочным.

Если ваш

   c = new TcpClient(ip, port);

терпит неудачу, тогда ничего не слушает. В противном случае он будет подключаться, даже если какой-либо другой компьютер/приложение имеет сокет, открытый для этого ip и порта.

Ответ 10

ipGlobalProperties.GetActiveTcpConnections() не возвращает соединения в состоянии прослушивания.

Порт может использоваться для прослушивания, но ни с кем связанным с ним описанным выше способом не будет работать.

Ответ 11

Если я не очень ошибаюсь, вы можете использовать System.Network.whatever, чтобы проверить.

Однако это всегда будет связано с состоянием гонки.

Канонический способ проверки - это попытаться прослушивать этот порт. Если вы получили сообщение об ошибке, что порт не был открыт.

Я думаю, что это часть того, почему bind() и listen() - это два отдельных системных вызова.

Ответ 12

Знайте временное окно между вами, чтобы проверить, и как только вы попытаетесь сделать соединение, какой-то процесс может занять порт - классический TOCTOU. Почему бы вам просто не попытаться подключиться? Если это не удается, вы знаете, что порт недоступен.

Ответ 13

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

Каждое соединение TCP/IP идентифицируется по 4 значениям: удаленный IP-адрес, номер удаленного порта, локальный IP-адрес, номер локального порта, но вам нужно знать только удаленный IP-адрес и номер удаленного порта для установления соединения.

Когда вы создаете tcp-соединение, используя

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

Ваша система автоматически присвоит вашему соединению один из многих бесплатных номеров локальных портов. Вам не нужно ничего делать. Вы также можете проверить, открыт ли удаленный порт. но нет лучшего способа сделать это, чем просто пытаться подключиться к нему.

Ответ 14

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

Ответ 15

Из доступных портов я бы исключил:

  • активные 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

Ответ 16

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

Ответ 17

Проверить код ошибки 10048

try
{
    TcpListener tcpListener = new TcpListener(ipAddress, portNumber);
    tcpListener.Start();
}
catch(SocketException ex)
{
    if(ex.ErrorCode == 10048)
    {
        MessageBox.Show("Port " + portNumber + " is currently in use.");
    }
    return;
}

Ответ 18

попробуйте это, в моем случае номер порта для созданного объекта недоступен, поэтому я придумал этот

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