Question

Je dois connaître l'adresse externe de l'ordinateur sur lequel une application C # est en cours d'exécution.

Dans l'application, j'ai une connexion (via .NET remoting) à un serveur. Existe-t-il un bon moyen d’obtenir l’adresse du client côté serveur?

(J'ai modifié la question pour être un peu plus clair. Je m'excuse auprès de toutes les gentilles personnes qui ont fait de leur mieux pour répondre à la question, alors que j'étais peut-être un peu trop vague)

Solution:
J'ai trouvé un moyen qui fonctionnait très bien pour moi. En implémentant un IServerChannelSinkProvider et un IServerChannelSink personnalisés où j'ai accès à CommonTransportKeys.IPAddress, il est facile d'ajouter l'ip du client sur le CallContext.

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, 
    IMessage requestmessage, ITransportHeaders requestHeaders, 
    System.IO.Stream requestStream, out IMessage responseMessage, 
    out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
    try
    {
        // Get the IP address and add it to the call context.
        IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
        CallContext.SetData("ClientIP", ipAddr);
    }
    catch (Exception)
    {
    }

    sinkStack.Push(this, null);
    ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
        requestStream, out responseMessage, out responseHeaders, out responseStream);

    return srvProc;
}

Et ensuite (lorsque je reçois une demande d'un client), obtenez simplement l'adresse IP du CallContext comme ceci.

public string GetClientIP()
{
    // Get the client IP from the call context.
    object data = CallContext.GetData("ClientIP");

    // If the data is null or not a string, then return an empty string.
    if (data == null || !(data is IPAddress))
        return string.Empty;

    // Return the data as a string.
    return ((IPAddress)data).ToString();
}

Je peux maintenant renvoyer l'IP au client.

Était-ce utile?

La solution 5

J'ai trouvé un moyen qui fonctionnait bien pour moi. En implémentant un IServerChannelSinkProvider et un IServerChannelSink personnalisés où j'ai accès à CommonTransportKeys.IPAddress, il est facile d'ajouter l'ip du client sur le CallContext.

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, 
    IMessage requestmessage, ITransportHeaders requestHeaders, 
    System.IO.Stream requestStream, out IMessage responseMessage, 
    out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
    try
    {
        // Get the IP address and add it to the call context.
        IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
        CallContext.SetData("ClientIP", ipAddr);
    }
    catch (Exception)
    {
    }

    sinkStack.Push(this, null);
    ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
        requestStream, out responseMessage, out responseHeaders, out responseStream);

    return srvProc;
}

Et ensuite (lorsque je reçois une demande d'un client), obtenez simplement l'adresse IP du CallContext comme ceci.

public string GetClientIP()
{
    // Get the client IP from the call context.
    object data = CallContext.GetData("ClientIP");

    // If the data is null or not a string, then return an empty string.
    if (data == null || !(data is IPAddress))
        return string.Empty;

    // Return the data as a string.
    return ((IPAddress)data).ToString();
}

Je peux maintenant renvoyer l'IP au client.

Autres conseils

C’est l’une de ces questions pour lesquelles il faut approfondir et peut-être repenser le problème initial; dans ce cas, "Pourquoi avez-vous besoin d’une adresse IP externe?"

Le problème est que l'ordinateur peut ne pas avoir d'adresse IP externe. Par exemple, mon ordinateur portable a une adresse IP interne (192.168.x.y) attribuée par le routeur. Le routeur lui-même a une adresse IP interne, mais son adresse "externe" L'adresse IP est également interne. Il n’est utilisé que pour communiquer avec le modem DSL, qui possède en fait une adresse IP externe avec accès Internet.

La vraie question est donc: "Comment puis-je obtenir l'adresse IP Internet d'un périphérique à deux sauts?" Et la réponse est généralement non. du moins pas sans utiliser un service tel que whatismyip.com que vous avez déjà congédié, ou faire un piratage vraiment énorme impliquant le codage en dur du mot de passe du modem DSL dans votre application, interroger le modem DSL et récurer la page d'administration (et que Dieu vous aide si le modem est remplacé).

EDIT: Maintenant, appliquez-le à la question refactorisée: "Comment obtenir l'adresse IP de mon client à partir d'un composant .NET du serveur?" Tout comme whatismyip.com, le mieux que le serveur puisse faire est de vous donner l’adresse IP de votre appareil connecté à Internet, qui n’est probablement pas l’adresse IP réelle de l’ordinateur exécutant l’application. Pour revenir à mon ordinateur portable, si mon adresse IP face à Internet était 75.75.75.75 et mon adresse IP locale 192.168.0.112, le serveur ne pourrait voir que l’adresse IP 75.75.75.75. Cela ira aussi loin que mon modem DSL. Si votre serveur souhaitait établir une connexion distincte avec mon ordinateur portable, je devrais au préalable configurer le modem DSL et tous les routeurs entre ce dernier et mon ordinateur portable afin de reconnaître les connexions entrantes provenant de votre serveur et de les acheminer correctement. Il existe plusieurs façons de procéder, mais cela sort du cadre de ce sujet.

Si vous essayez en fait d'établir une connexion entre le serveur et le client, repensez votre conception, car vous explorez le territoire de la technologie WTF (ou du moins, en rendant votre application encore plus difficile à déployer).

Dns.GetHostEntry (Dns.GetHostName ()); retournera un tableau d'adresses IP. Le premier devrait être l'adresse IP externe, le reste sera celui derrière le NAT.

Donc:

IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
string externalIP = IPHost.AddressList[0].ToString();

EDIT:

Selon certaines informations, cela ne fonctionnerait pas chez certaines personnes. Cela me convient, mais peut-être que cela ne fonctionnera pas en fonction de la configuration de votre réseau.

Il vaut mieux utiliser http://www.whatismyip.com/automation/n09230945.asp il ne génère que l'adresse IP destinée aux recherches automatisées.

Si vous souhaitez que votre site ne dépende pas de quelqu'un d'autre, créez votre propre page http://www.unkwndesign.com/ip.php est juste un script rapide:

<?php
echo 'Your Public IP is: ' . 

Il vaut mieux utiliser http://www.whatismyip.com/automation/n09230945.asp il ne génère que l'adresse IP destinée aux recherches automatisées.

Si vous souhaitez que votre site ne dépende pas de quelqu'un d'autre, créez votre propre page http://www.unkwndesign.com/ip.php est juste un script rapide:

<*>

Le seul inconvénient est qu’il récupérera uniquement l’adresse IP externe de l’interface utilisée pour créer la demande.

SERVER['REMOTE_ADDR']; ?>

Le seul inconvénient est qu’il récupérera uniquement l’adresse IP externe de l’interface utilisée pour créer la demande.

La réponse de Jonathan Holland est fondamentalement correcte, mais il convient de noter que les appels d'API derrière Dns.GetHostByName prennent assez de temps et qu'il est judicieux de mettre en cache les résultats afin que le code ne soit appelé qu'une seule fois.

Le problème principal est que l'adresse IP publique n'est pas nécessairement corrélée à l'ordinateur local exécutant l'application. Il est traduit du réseau interne à travers le pare-feu. Obtenir réellement l'adresse IP publique sans interroger le réseau local, c'est demander à une page Internet et renvoyer le résultat. Si vous ne souhaitez pas utiliser un site de type WhatIsMyIP.com accessible au public, vous pouvez facilement en créer un et l'héberger vous-même - de préférence en tant que service Web, afin que vous puissiez effectuer un simple appel conforme au format savon à partir de votre application. Vous ne feriez pas nécessairement une capture d'écran autant qu'un post en coulisse et ne lirez pas la réponse.

Si vous souhaitez uniquement l'adresse IP liée à l'adaptateur, vous pouvez utiliser WMI et la classe Win32_NetworkAdapterConfiguration.

http://msdn.microsoft.com/ en-us / library / aa394217 (VS.85) .aspx

La solution de Patrik fonctionne pour moi!

J'ai apporté un changement important. Dans le message de processus, je règle le CallContext à l'aide du code suivant:

// try to set the call context
LogicalCallContext lcc = (LogicalCallContext)requestMessage.Properties["__CallContext"];
if (lcc != null)
{
    lcc.SetData("ClientIP", ipAddr);
}

Ceci place l’adresse IP dans le bon CallContext afin qu’elle puisse être récupérée ultérieurement avec GetClientIP () .

Eh bien, en supposant que vous ayez un System.Net.Sockets.TcpClient connecté à votre client, vous pouvez (sur le serveur) utiliser client.Client.RemoteEndPoint . Cela vous donnera un System.Net.EndPoint pointant vers le client; devrait contenir une instance de la sous-classe System.Net.IPEndPoint , bien que je ne sois pas sûr des conditions pour cela. Ensuite, vous pouvez vérifier que c'est la propriété Address pour obtenir l'adresse du client.

En bref, nous avons

using (System.Net.Sockets.TcpClient client = whatever) {
    System.Net.EndPoint ep = client.Client.RemoteEndPoint;
    System.Net.IPEndPoint ip = (System.Net.IPEndPoint)ep;
    DoSomethingWith(ip.Address);
}

Bonne chance.

Je pense qu'en théorie, vous ne pouvez pas faire cela en étant derrière un routeur (par exemple, en utilisant des plages d'adresses IP non valides) sans utiliser une "aide" externe.

Vous pouvez analyser la page renvoyée en effectuant une requête Web de http://whatismyipaddress.com

.

http://www.dreamincode.net/forums/showtopic24692.htm

La méthode la plus fiable consiste à consulter un site tel que http://checkip.dyndns.org/ ou similaire, car jusqu’à ce que vous utilisiez l’extérieur de votre réseau, vous ne trouviez pas votre IP externe. Cependant, le codage en dur d'une telle URL demande un échec éventuel. Vous voudrez peut-être effectuer cette vérification uniquement si l'adresse IP actuelle ressemble à une RFC1918 . ( 192.168.xx étant le plus familier de ceux-ci.

Si vous ne le faites pas, vous pouvez implémenter votre propre service similaire, installé à l'extérieur du pare-feu, afin que vous sachiez au moins s'il est en panne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top