Получить внешний IP-адрес через remoting в C#
мне нужно узнать внешний IP компьютера, на котором работает приложение C#.
в приложении у меня есть соединение (через .NET remoting) с сервером. Есть ли хороший способ получить адрес клиента на стороне сервера?
(я отредактировал вопрос, чтобы быть немного более ясным. Я извиняюсь перед всеми добрыми людьми, которые сделали все возможное, чтобы ответить на вопрос, когда я, возможно, был немного слишком vague)
устранение:
Я нашел способ, который работал для меня. Реализуя пользовательский IServerChannelSinkProvider и IServerChannelSink, где у меня есть доступ к CommonTransportKeys.IPAddress, легко добавить ip-адрес клиента в 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;
}
а затем позже (когда я получаю запрос от клиента) просто получить IP из CallContext, как это.
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();
}
теперь я могу отправить IP в клиенте.
12 ответов
Это один из тех вопросов, где вы должны смотреть глубже и, возможно, переосмыслить исходную проблему, в этом случае, "зачем вам нужен внешний IP-адрес?"
проблема в том, что компьютер может не иметь внешнего IP-адреса. Например, мой ноутбук имеет внутренний IP адрес (192.168.X. y) назначается маршрутизатором. Сам роутер имеет внутренний IP-адрес, но его "внешний" IP-адрес также является внутренним. Он используется только для связи с модемом DSL, который на самом деле имеет внешние сети IP-адрес.
таким образом, реальный вопрос становится: "как мне получить IP-адрес устройства, обращенный к интернету, 2?- И ответ, как правило, таков: нет; по крайней мере, без использования таких услуг, как whatismyip.com что вы уже уволили, или делать действительно массовый хак с участием hardcoding пароль DSL модема в приложение и запрос DSL модема и экран-выскабливание страницы администратора (и Бог поможет вам, если модем когда-либо замещаемый.)
EDIT: теперь, чтобы применить это к рефакторированному вопросу: "Как получить IP-адрес моего клиента из компонента сервера .NET?- Как ... whatismyip.com, лучшее, что сервер сможет сделать, это дать вам IP-адрес вашего интернет-устройства, которое вряд ли будет фактическим IP-адресом компьютера, на котором работает приложение. Возвращаясь к моему ноутбуку, если мой интернет IP был 75.75.75.75 и локальной сети ИС 192.168.0.112, сервер сможет см. IP-адрес 75.75.75.75. Это дойдет до моего DSL-модема. Если ваш сервер хотел бы сделать отдельное соединение обратно к моему ноутбуку, мне сначала нужно настроить DSL-модем и любые маршрутизаторы между ним и моим ноутбуком, чтобы распознавать входящие соединения с вашего сервера и маршрутизировать их соответствующим образом. Есть несколько способов сделать это, но это выходит за рамки данной темы.
Если вы на самом деле пытаетесь установить соединение с сервером клиенту, переосмыслить ваш дизайн, потому что вы вникаете в территорию WTF (или, по крайней мере, делаете ваше приложение намного сложнее развернуть).
Dns.GetHostEntry (Dns.GetHostName ()); вернет массив IP-адресов. Первым должен быть внешний IP, остальные будут за NAT.
Так:
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
string externalIP = IPHost.AddressList[0].ToString();
изменить:
есть информация, что это не работает для некоторых людей. Для меня это так, но, возможно, в зависимости от конфигурации вашей сети это может не сработать.
лучше просто использовать http://www.whatismyip.com/automation/n09230945.asp он выводит IP только для автоматизированных поисков.
если вы хотите что-то, что не полагается на кого-то другого, поместите свою собственную страницу http://www.unkwndesign.com/ip.php это просто быстрый скрипт:
<?php
echo 'Your Public IP is: ' . $_SERVER['REMOTE_ADDR'];
?>
единственным недостатком здесь является то, что он будет извлекать только внешний IP интерфейса, который использовался для создания запроса.
ответ Джонатана Холланда принципиально правильный, но стоит добавить, что API вызывает Dns.GetHostByName довольно трудоемки, и это хорошая идея, чтобы кэшировать результаты, так что код должен быть вызван только один раз.
Я нашел способ, который работал для меня. Реализуя пользовательский IServerChannelSinkProvider и IServerChannelSink, где у меня есть доступ к CommonTransportKeys.IPAddress, легко добавить ip-адрес клиента в 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;
}
а затем позже (когда я получаю запрос от клиента) просто получить IP из CallContext, как это.
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();
}
теперь я могу отправить IP в клиенте.
основная проблема заключается в том, что общедоступный IP-адрес не обязательно коррелирует с локальным компьютером, на котором запущено приложение. Он переводится из внутренней сети через брандмауэр. Чтобы действительно получить общедоступный IP-адрес без опроса локальной сети, нужно сделать запрос на интернет-страницу и вернуть результат. Если вы не хотите использовать общедоступный WhatIsMyIP.com тип сайта вы можете легко создать и разместить его самостоятельно-желательно в качестве веб-сервиса, чтобы вы могли простой soap совместимый вызов к нему из вашего приложения. Вы не обязательно будете делать захват экрана столько, сколько закулисный пост и читать ответ.
Если вы просто хотите IP, который привязан к адаптеру, вы можете использовать WMI и класс Win32_NetworkAdapterConfiguration.
http://msdn.microsoft.com/en-us/library/aa394217 (VS.85).aspx
решение Патрика работает для меня!
Я один важное изменение. В процессе сообщения я установил CallContext
используя этот код:
// try to set the call context
LogicalCallContext lcc = (LogicalCallContext)requestMessage.Properties["__CallContext"];
if (lcc != null)
{
lcc.SetData("ClientIP", ipAddr);
}
это помещает ip-адрес в правильный CallContext, поэтому его можно позже получить с помощью
GetClientIP()
.
Ну, если у вас есть System.Net.Sockets.TcpClient
подключается к вашему клиенту, вы можете (на сервере) использовать client.Client.RemoteEndPoint
. Это даст вам System.Net.EndPoint
указывая на клиента; это должны содержит экземпляр System.Net.IPEndPoint
подкласс, хотя я не уверен, что условия для этого. После кастинга на это вы можете проверить, что это Address
свойство для получения адреса клиента.
короче говоря, у нас есть
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);
}
удачи.
Я считаю, что теоретически вы не можете сделать это, находясь за маршрутизатором (например, используя недопустимые диапазоны ip) без использования внешней "помощи".
вы можете в основном проанализировать страницу, возвращенную, выполнив WebRequest http://whatismyipaddress.com
самый надежный способ сделать это-проверить сайт, такой как http://checkip.dyndns.org/ или подобное, потому что пока вы фактически не выйдете за пределы своей сети, вы не сможете найти свой внешний IP. Однако жесткое кодирование такого URL-адреса требует возможного сбоя. Вы можете только выполнить эту проверку, если текущий IP-адрес выглядит как RFC1918 частный адрес (192.168.x.x
будучи самым знакомым из них.
в противном случае вы можете реализовать свой собственный, аналогично, служба сидит снаружи брандмауэра, поэтому вы по крайней мере будете знать, если она сломана.