Domanda

Ho bisogno di scoprire il esterno IP del computer su cui è in esecuzione un'applicazione C#.

Nell'applicazione ho una connessione (tramite .NET remoting) a un server.Esiste un buon modo per ottenere l'indirizzo del client sul lato server?

(Ho modificato la domanda, per essere un po' più chiaro.Mi scuso con tutte le gentili persone che hanno fatto del loro meglio per rispondere alla domanda, quando forse ero un po' troppo vago)

Soluzione:
Ho trovato un modo che ha funzionato benissimo per me.Implementando un IServerChannelSinkProvider e un IServerChannelSink personalizzati in cui ho accesso a CommonTransportKeys.IPAddress, è facile aggiungere l'IP del client su 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;
}

E poi in seguito (quando ricevo una richiesta da un client) ottengo semplicemente l'IP da CallContext in questo modo.

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();
}

Ora posso inviare l'IP al client.

È stato utile?

Soluzione 5

Ho trovato un modo che ha funzionato benissimo per me.Implementando un IServerChannelSinkProvider e un IServerChannelSink personalizzati in cui ho accesso a CommonTransportKeys.IPAddress, è facile aggiungere l'IP del client su 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;
}

E poi in seguito (quando ricevo una richiesta da un client) ottengo semplicemente l'IP da CallContext in questo modo.

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();
}

Ora posso inviare l'IP al client.

Altri suggerimenti

Questa è una di quelle domande in cui devi guardare più in profondità e magari ripensare il problema originale;in questo caso, "Perché hai bisogno di un indirizzo IP esterno?"

Il problema è che il computer potrebbe non avere un indirizzo IP esterno.Ad esempio, il mio laptop ha un indirizzo IP interno (192.168.x.y) assegnato dal router.Il router stesso ha un indirizzo IP interno, ma anche il suo indirizzo IP "esterno" è interno.Viene utilizzato solo per comunicare con il modem DSL, che in realtà ha l'indirizzo IP esterno rivolto a Internet.

Quindi la vera domanda diventa: "Come faccio a ottenere l'indirizzo IP rivolto a Internet di un dispositivo 2 salta via?" E la risposta è generalmente, no;almeno non senza utilizzare un servizio come whatismyip.com che hai già abbandonato, o senza eseguire un attacco davvero massiccio che prevede l'hardcoding della password del modem DSL nella tua applicazione e l'interrogazione del modem DSL e lo screen-scraping della pagina di amministrazione (e Dio ti aiuti se il modem viene mai sostituito).

MODIFICARE:Ora per applicare questo alla domanda refattorata, "Come posso ottenere l'indirizzo IP del mio client da un componente Server .NET?" Come Whatismyip.com, il migliore che il server sarà in grado di fare è darti l'indirizzo IP del tuo dispositivo rivolto a Internet, che è improbabile che sia l'indirizzo IP effettivo del computer che esegue l'applicazione.Tornando al mio laptop, se il mio IP connesso a Internet fosse 75.75.75.75 e l'IP LAN fosse 192.168.0.112, il server sarebbe in grado di vedere solo l'indirizzo IP 75.75.75.75.Questo porterà fino al mio modem DSL.Se il tuo server volesse stabilire una connessione separata al mio laptop, dovrei prima configurare il modem DSL e tutti i router tra esso e il mio laptop per riconoscere le connessioni in entrata dal tuo server e instradarle in modo appropriato.Esistono alcuni modi per eseguire questa operazione, ma non rientrano nell'ambito di questo argomento.

Se stai effettivamente tentando di stabilire una connessione dal server al client, ripensa il tuo progetto perché stai approfondendo il territorio del WTF (o almeno, rendendo la tua applicazione molto più difficile da distribuire).

Dns.GetHostEntry(Dns.GetHostName());restituirà un array di indirizzi IP.Il primo dovrebbe essere l'IP esterno, il resto sarà quello dietro NAT.

COSÌ:

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

MODIFICARE:

Ci sono rapporti secondo cui questo non funziona per alcune persone.A me funziona, ma forse a seconda della configurazione di rete potrebbe non funzionare.

Meglio semplicemente usare http://www.whatismyip.com/automation/n09230945.asp restituisce l'IP solo per le ricerche automatizzate.

Se vuoi qualcosa che non dipenda da qualcun altro, crea la tua pagina http://www.unkwndesign.com/ip.php è solo uno script veloce:

<?php
echo 'Your Public IP is: ' . $_SERVER['REMOTE_ADDR'];
?>

L'unico svantaggio è che recupererà solo l'IP esterno dell'interfaccia utilizzata per creare la richiesta.

La risposta di Jonathan Holland è fondamentalmente corretta, ma vale la pena aggiungere che le chiamate API dietro Dns.GetHostByName richiedono molto tempo ed è una buona idea memorizzare nella cache i risultati in modo che il codice debba essere chiamato solo una volta.

Il problema principale è che l'indirizzo IP pubblico non è necessariamente correlato al computer locale che esegue l'applicazione.Viene tradotto dalla rete interna attraverso il firewall.Per ottenere veramente l'IP pubblico senza interrogare la rete locale è fare una richiesta ad una pagina internet e restituire il risultato.Se non desideri utilizzare un sito di tipo WhatIsMyIP.com disponibile pubblicamente, puoi crearne facilmente uno e ospitarlo tu stesso, preferibilmente come servizio Web in modo da poter effettuare una semplice chiamata conforme a soap dall'interno della tua applicazione.Non dovresti necessariamente catturare uno schermo tanto quanto pubblicare un post dietro le quinte e leggere la risposta.

Se desideri solo l'IP associato all'adattatore, puoi utilizzare WMI e la classe Win32_NetworkAdapterConfiguration.

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

La soluzione di Patrik funziona per me!

ho fatto uno cambiamento importante.Nel messaggio di processo ho impostato il file CallContext utilizzando questo codice:

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

Ciò inserisce l'indirizzo IP nel CallContext corretto, in modo che possa essere successivamente recuperatoGetClientIP().

Bene, supponendo che tu abbia un System.Net.Sockets.TcpClient connesso al tuo client, puoi (sul server) utilizzare client.Client.RemoteEndPoint.Questo ti darà un System.Net.EndPoint indicando il cliente;Quello Dovrebbe contenere un'istanza di System.Net.IPEndPoint sottoclasse, anche se non sono sicuro delle condizioni per questo.Dopo aver effettuato il casting, puoi verificarlo Address proprietà per ottenere l'indirizzo del cliente.

In breve, abbiamo

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);
}

Buona fortuna.

Credo che teoricamente non sia possibile fare una cosa del genere mentre si è dietro un router (ad es.utilizzando intervalli IP non validi) senza utilizzare un "aiuto" esterno.

In pratica puoi analizzare la pagina restituita eseguendo una WebRequest of http://whatismyipaddress.com

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

Il modo più affidabile per farlo è controllare un sito come http://checkip.dyndns.org/ o simili, perché finché non esci effettivamente dalla tua rete, non puoi trovare il tuo IP esterno.Tuttavia, l'hardcoding di un URL di questo tipo richiede un eventuale errore.Potresti voler eseguire questo controllo solo se l'IP corrente assomiglia a un RFC1918 indirizzo privato (192.168.x.x essendo il più familiare di questi.

In caso contrario, puoi implementare il tuo servizio simile esterno al firewall, così saprai almeno se è rotto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top