En C #, utiliser un TcpClient ou généralement 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);
Puisque vous utilisez une TcpClient
, cela signifie que vous vérifiez les ports ouverts TCP. Il y a beaucoup de bons objets disponibles dans System.Net.NetworkInformation namespace.
Utilisez l'objet IPGlobalProperties
pour accéder à un tableau d'objets TcpConnectionInformation
, que vous pouvez ensuite interroger à propos de l'adresse IP et du port du terminal.
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 du mauvais côté de l'Intertube. C'est le serveur qui ne peut avoir qu'un seul port ouvert. Un code:
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 normalement autorisée.
Lorsque vous configurez une connexion TCP, le 4-Tuple (source-ip, source-port, dest-ip, dest-port) doit être unique - ceci afin de garantir que les paquets sont livrés au bon endroit.
Le côté server est soumis à une restriction supplémentaire selon laquelle un seul programme serveur peut se lier à un numéro de port entrant (en supposant une adresse IP unique; les serveurs multi-NIC ont d'autres pouvoirs, mais nous n'avons pas besoin de les discuter ici).
Donc, côté serveur, vous:
Du côté du client, c'est généralement un peu plus simple:
Il est non obligatoire que l’adresse IP/le port de destination soit unique, car cela ne ferait en sorte qu’une seule personne à la fois puisse utiliser Google, ce qui détruirait plutôt son modèle commercial.
Cela signifie que vous pouvez même faire des choses merveilleuses comme le FTP multi-sessions 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. Les torrents 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 brouhaha (désolé), la réponse à votre question spécifique est qu'il n'est pas nécessaire 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 certainement le zéro sous couverture et le système vous en donnera un non utilisé.
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, les autres utilisateurs ne peuvent pas l'utiliser tant qu'il n'est pas gratuit. - ALi
Vous avez mal compris ce qui se passe ici.
Les paramètres de TcpClient (...) sont ceux du serveur ip et du port du serveur auquel vous souhaitez vous connecter.
TcpClient sélectionne un port local transitoire dans le pool disponible pour communiquer avec le serveur. Il n'est pas nécessaire de vérifier la disponibilité du port local car celui-ci est automatiquement géré par la couche winsock.
Si vous ne pouvez pas vous connecter au serveur en utilisant le fragment de code ci-dessus, le problème peut être lié à un ou plusieurs problèmes. (c'est-à-dire que l'adresse IP et/ou le port du serveur sont incorrects, le serveur distant n'est pas disponible, etc.)
Merci pour ce conseil. J'avais besoin de la même fonctionnalité mais côté serveur pour vérifier si un port était utilisé, je l'ai donc 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. Je devais le modifier pour mon usage. Je devais vérifier si un port était écouté et pas nécessairement actif. Pour cela j'ai remplacé
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
avec
IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.
J'ai itéré le tableau des noeuds finaux en vérifiant que la valeur de mon port était introuvable.
netstat! C'est un utilitaire de ligne de commande réseau livré avec Windows. Il montre toutes les connexions établies actuelles et tous les ports en cours d'écoute. Vous pouvez utiliser ce programme pour vérifier, mais si vous voulez le faire à partir de code, consultez l'espace de noms System.Net.NetworkInformation? C'est un nouvel espace de noms à partir de 2.0. Il y a des bonbons là-bas. Mais finalement, si vous voulez obtenir le même type d’information disponible par le biais de la commande netstat, vous devez obtenir P/Invoke ...
Cet espace de noms contient un ensemble de classes que vous pouvez utiliser pour comprendre le réseau.
Je ne pouvais pas trouver cette vieille pièce de code, mais je pense que vous pouvez écrire quelque chose de similaire vous-même. Un bon début est de vérifier le API IP Helper . Google MSDN pour la fonction GetTcpTable WINAPI et utilisez P/Invoke pour énumérer jusqu'à obtenir les informations dont vous avez besoin.
ipGlobalProperties.GetActiveTcpConnections()
ne renvoie pas de connexions dans l'état d'écoute.
Le port peut être utilisé pour l'écoute, mais sans personne connectée, la méthode décrite ci-dessus ne fonctionnera pas.
Si je ne me trompe pas vraiment, vous pouvez utiliser System.Network.wwhat pour vérifier.
Cependant, cela entraînera toujours une condition de concurrence.
La manière canonique de vérifier est d'essayer d'écouter sur ce port. Si vous obtenez une erreur, ce port n'était pas ouvert.
Je pense cela explique en partie pourquoi bind () et listen () sont deux appels système distincts.
Vous dites
Je veux dire qu'il n'est pas utilisé par aucun autre application. Si une application utilise un port que d'autres ne peuvent pas utiliser jusqu'à ce qu'il devienne libre.
Mais vous pouvez toujours vous connecter à un port pendant que d'autres l'utilisent si quelque chose y écoute. Sinon, le port HTTP 80 serait un gâchis.
Si ton
c = new TcpClient(ip, port);
échoue, alors rien n'y écoute. Sinon, il se connectera, même si une autre machine/application possède un socket ouvert à cette adresse IP et ce 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;
}
Sachez que la fenêtre temporelle entre la vérification et le moment où vous essayez d'établir une connexion peut prendre le port - classique TOCTOU . Pourquoi n'essayez-vous pas simplement de vous connecter? Si cela échoue, vous savez que le port n'est pas disponible.
Je exclurais des ports disponibles:
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
Vous n'avez pas besoin de savoir quels ports sont ouverts sur votre ordinateur local pour vous connecter à un service distant TCP (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 vous devez uniquement connaître l'adresse IP distante et le numéro de port distant pour établir une connexion.
Lorsque vous créez une connexion TCP en utilisant
TcpClient c; C = new TcpClient (remote_ip, remote_port);
Votre système attribuera automatiquement l'un des nombreux numéros de port locaux gratuits à votre connexion. Vous n'avez rien à faire .. Vous pouvez également vérifier si un port distant est ouvert. mais il n'y a pas de meilleur moyen de le faire que d'essayer de s'y connecter.
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.");
}
}
}
Recherchez le code d'erreur 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;
}