В C # как проверить, доступен ли порт TCP? - PullRequest
111 голосов
/ 20 февраля 2009

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

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

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

Ответы [ 18 ]

202 голосов
/ 20 февраля 2009

Поскольку вы используете 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.
40 голосов
/ 20 февраля 2009

Вы находитесь не на том конце 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");
  }

Сбой с:

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

19 голосов
/ 07 апреля 2009

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

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

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

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

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

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

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

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

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

15 голосов
/ 03 апреля 2009
TcpClient c;

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

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

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

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

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

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

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

14 голосов
/ 12 ноября 2010

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

 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 голосов
/ 08 мая 2010

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

TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

с

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

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

6 голосов
/ 20 февраля 2009
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);
}
3 голосов
/ 20 февраля 2009

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

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

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

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

2 голосов
/ 09 апреля 2009

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

Однако, это всегда будет связано с расой.

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

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

2 голосов
/ 24 февраля 2009

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

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

...