En C#, Comment vérifier si un port TCP est disponible?
En C# pour utiliser un TcpClient ou généralement pour se connecter à un socket Comment puis-je d'abord vérifier si un certain port est libre sur ma machine?
plus d'infos: C'est le code que j'utilise:
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
17 réponses
Puisque vous utilisez un TcpClient
, cela signifie que vous vérifiez les ports TCP ouverts. Il y a beaucoup de bons objets disponibles dans l'espace de noms System.Net.NetworkInformation.
Utilisez l'objet IPGlobalProperties
pour accéder à un tableau d'objets TcpConnectionInformation
, que vous pouvez ensuite interroger sur l'adresse IP et le port du point de terminaison.
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.
Vous êtes sur le mauvais bout de L'Intertube. C'est le serveur qui ne peut avoir qu'un seul port particulier ouvert. Certains codes:
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
try {
TcpListener tcpListener = new TcpListener(ipAddress, 666);
tcpListener.Start();
}
catch (SocketException ex) {
MessageBox.Show(ex.Message, "kaboom");
}
Échoue avec:
Une Seule utilisation de chaque adresse de socket (protocole/adresse réseau/port) est habituellement autorisée.
Lorsque vous configurez une connexion TCP, le 4-tuple (source-ip, source-port, dest-ip, dest-port) doit être unique - c'est pour s'assurer que les paquets sont livrés au bon endroit.
Il y a une autre restriction sur le côté Serveur qu'un seul programme serveur peut se lier à un numéro de port entrant (en supposant une adresse IP; les serveurs multi-NIC ont d'autres pouvoirs mais nous n'avons pas besoin d'en discuter ici).
Donc, à la fin du serveur, vous:
- créer un socket.
- lie ce socket à un port.
- écoutez sur ce port.
- accepte les connexions sur ce port. et il peut y avoir plusieurs connexions à venir (une par client).
À la fin du client, c'est généralement un peu plus simple:
- créer un socket.
- ouvrez la connexion. Lorsqu'un client ouvre la connexion, il spécifie l'adresse ip et le port du serveur . Il Peut spécifier son port source mais utilise généralement zéro qui résulte dans le système lui attribuant un port libre automatiquement.
Il n'y a aucune exigence que L'adresse IP/port de destination soit unique, car cela permettrait à une seule personne à la fois d'utiliser Google, ce qui détruirait assez bien leur modèle commercial.
Cela signifie que vous pouvez même faire des choses merveilleuses comme le FTP multi-session puisque vous configurez plusieurs sessions où la seule différence est votre port source, vous permettant de télécharger des morceaux en parallèle. Torrent sont un peu différents en ce sens que la destination de chaque session est généralement différente.
Et, après tout ce gaufrage (désolé), la réponse à votre question spécifique est que vous n'avez pas besoin de spécifier un port libre. Si vous vous connectez à un serveur avec un appel qui ne spécifie pas votre port source, il utilisera presque certainement zéro sous les couvertures et le système vous en donnera un inutilisé.
TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);
...Comment puis-je d'abord vérifier si un certain port est libre sur ma machine?
Je veux dire qu'il n'est utilisé par aucune autre application. Si une application utilise un port, d'autres ne peuvent pas l'utiliser jusqu'à ce qu'il devienne libre. - Ali
Vous avez mal compris ce qui se passe ici.
TcpClient(...) les paramètres sont de l'ip du serveur et du port du serveur auquel vous souhaitez vous connecter.
Le TcpClient sélectionne un port local transitoire dans le pool disponible pour communiquer pour le serveur. Il n'est pas nécessaire de vérifier la disponibilité du port local car il est automatiquement géré par la couche winsock.
Dans le cas où vous ne pouvez pas vous connecter au serveur en utilisant le fragment de code ci-dessus, le problème pourrait être un ou plusieurs de plusieurs. (c'est-à-dire que l'ip et/ou le port du serveur sont incorrects, que le serveur distant n'est pas disponible, etc..)
Merci pour ce conseil. J'avais besoin de la même fonctionnalité mais du côté serveur pour vérifier si un Port était utilisé, donc je l'ai modifié pour ce code.
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);
}
Merci pour la réponse jro. J'ai dû le modifier pour mon utilisation. J'avais besoin de vérifier si un port était écouté, et pas neccessarily actif. Pour cela, j'ai remplacé
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
Avec
IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.
J'ai itéré le tableau de points de terminaison en vérifiant que ma valeur de port n'a pas été trouvée.
Netstat! C'est un utilitaire de ligne de commande réseau qui est livré avec windows. Il montre toutes les connexions établies actuelles et tous les ports actuellement écoutés. Vous pouvez utiliser ce programme pour vérifier, mais si vous voulez le faire à partir du code, regardez dans L'espace de noms System.Net.NetworkInformation? C'est un nouvel espace de noms à partir de 2.0. Il y a des friandises là-bas. Mais finalement si vous voulez obtenir le même genre d'informations qui est disponible via la commande netstat vous devrez résultat à P / Invoke...
Mise À Jour: System. Net. NetworkInformation
Cet espace de noms contient un tas de classes que vous pouvez utiliser pour trouver des choses sur le réseau.
Je n'ai pas pu trouver ce vieux pice de code mais je pense que vous pouvez écrire quelque chose de similaire vous-même. Un bon début est de vérifier l'API IP Helper . Google MSDN pour la fonctionGETTCPTABLE WINAPI et utilisez P / Invoke pour énumérer jusqu'à ce que vous ayez les informations dont vous avez besoin.
Vous dites
Je veux dire qu'il n'est pas utilisé par tout autre application. Si une application utilise un port d'autres ne peuvent pas l'utiliser jusqu'à ce qu'il devient libre.
Mais vous pouvez toujours vous connecter à un port pendant que d'autres l'utilisent si quelque chose est à l'écoute. Sinon, le port http 80 serait un gâchis.
Si votre
c = new TcpClient(ip, port);
Échoue, alors rien n'écoute là-bas. Sinon, il se connectera, même si une autre machine / application a une prise ouverte à cela adresse ip et le port.
Si Je ne me trompe pas beaucoup, vous pouvez utiliser System.Réseau.que ce soit pour vérifier.
Cependant, cela entraînera toujours une condition de concurrence.
La façon canonique de vérifier est d'essayer d'écouter sur ce port. Si vous obtenez une erreur, ce port n'était pas ouvert.
Jepense que Cela fait partie de la raison pour laquelle bind() et listen() sont deux appels système distincts.
ipGlobalProperties.GetActiveTcpConnections()
ne renvoie pas les connexions dans L'État D'écoute.
Port peut être utilisé pour l'écoute, mais sans personne connecté à elle la méthode décrite ci-dessus ne fonctionnera pas.
Soyez conscient de la fenêtre de temps entre vous faites vérifier et le moment où vous essayez de faire la connexion un processus peut prendre le port-classique TOCTOU . Pourquoi ne pas essayer de vous connecter? Si cela échoue, vous savez que le port n'est pas disponible.
Vous n'avez pas besoin de savoir quels ports sont ouverts sur votre machine locale pour vous connecter à un service TCP distant (sauf si vous souhaitez utiliser un port local spécifique, mais ce n'est généralement pas le cas).
Chaque connexion TCP / IP est identifiée par 4 valeurs: adresse IP distante, numéro de port distant, adresse IP locale, numéro de port local, mais il vous suffit de connaître l'adresse IP distante et le numéro de port distant pour établir une connexion.
Lorsque vous créez une connexion tcp à l'aide de
TcpClient c; c = new TcpClient(remote_ip, remote_port);
Votre système sera automatiquement attribuez l'un des nombreux numéros de port locaux gratuits à votre connexion. Vous n'avez pas besoin de faire quoi que ce soit. Vous pouvez également vérifier si un port distant est ouvert. mais il n'y a pas de meilleure façon de le faire que de simplement essayer de s'y connecter.
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.");
}
}
}
Des ports disponibles, j'exclurais:
- connexions TCP actives
- écouteurs TCP actifs
- écouteurs UDP actifs
, Avec l'importation suivante:
using System.Net.NetworkInformation;
Vous pouvez utiliser la fonction suivante pour vérifier si un port est disponible ou non:
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;
}
, je vous donne une fonction similaire pour ceux qui utilisent 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
Essayez ceci, dans mon cas le numéro de port de l'objet créé n'était pas disponible, donc je suis venu avec ceci
IPEndPoint endPoint;
int port = 1;
while (true)
{
try
{
endPoint = new IPEndPoint(IPAddress.Any, port);
break;
}
catch (SocketException)
{
port++;
}
}