В C# как проверить, если TCP-порт доступен?
В C# для использования TcpClient или вообще для подключения к сокету как я могу сначала проверить, свободен ли определенный порт на моей машине?
подробнее:
Это код, который я использую:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
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