В локальной сети в броузере корректно работает примерно такой вот запрос
http://aa-bbb-cc:8080
Когда я пытаюсь выполнить вот такой код
Result := false;
with TTcpClient.Create(nil) do
try
RemoteHost := 'aa-bbb-cc';
RemotePort := '8080';
Result := Connect;
Disconnect;
finally
Free;
end;
соединение не устаналивается, Result = false
Но если вместо имени хоста подставить ip-адрес, то всё работает?
Можно ли как-то научить сокет понимать имя хоста? Если нет, то есть ли какой-то другой способ быстро проверить доступность хоста по сети, а не ждать ответа сервиса пока наступит таймаут?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
29-11-2024 14:01 | Сообщение от автора вопроса
>>> Тогда, может, читать файл hosts?
Честно скажу, не знаю, как у заказчика сеть организована. Вроде как всё в локалке (даже если подсети в разных городах связаны через интернет), но адреса вовсе не 192.168.X.X. Не думаю,что там всё так топорно через hosts, админы там крутые.
function HostToIP(Name: string; var Ip: string): Boolean;
var
wsdata : TWSAData;
hostName : array [0..255] of char;
hostEnt : PHostEnt;
addr : PChar;
begin
WSAStartup ($0101, wsdata);
try
gethostname (hostName, sizeof (hostName));
StrPCopy(hostName, Name);
hostEnt := gethostbyname (hostName);
if Assigned (hostEnt) then
if Assigned (hostEnt^.h_addr_list) then begin
addr := hostEnt^.h_addr_list^;
if Assigned (addr) then begin
IP := Format ('%d.%d.%d.%d', [byte (addr [0]),
byte (addr [1]), byte (addr [2]), byte (addr [3])]);
Result := True;
end
else
Result := False;
end
else
Result := False
else begin
Result := False;
end;
finally
WSACleanup;
end
end;
которая по имени хоста получает ip-адрес. Правда, пришлось её напильником доработать (написана жутко), но ip-адрес у заказчика определяет верно.
Я просто смотрю исходники (правда, дома у меня только Семёрка, но не думаю, что там что-то кардинально изменилось). Так вот, в реализации метода TCustomIpClient.Open есть такая строчка
То есть значение, которое мы присвоили свойству RemoteHost при установке соединения и так пройдет через LookupHostAddr. Вот поэтому и думаю, что не получится. Но в любом случае проверить из дома не смогу. Придётся ждать.
>>>Грустно. И непонятно. Что же не нравится в имени хоста?
Как пример.
Вы запускаете на локальном компьютере, и TcpClient, и TcpServer.
Для этого компьютера с помощь LookupHostAddr получаете такие адреса:
-127.0.0.1 127.0.0.1
-localhost 127.0.0.1
-mycomputer 192.168.1.2
Если для TcpClient.RemoteHost := 127.0.0.1 или := localhost, то он подключается к TcpServer, а если := mycomputer, то - нет.
Но зато, для TcpClient.RemoteHost = LookupHostAddr('mycomputer') соединение установится.
Сейчас посмотрел на 7-ке. Действительно, при вызове метода Open адрес подключения определяется из RemoteHost через вызов LookupHostAddr. То есть если у меня раньше Open не сработал, то LookupHostAddr мне тоже не поможет. Грустно. И непонятно. Что же не нравится в имени хоста? Ведь тот же броузер по имени хота соединяется без проблем.
>>>Подразумевается, что через TTcpClient.LookupHostAddr определяем по имени хоста ip-адрес, который и подставляем в TTcpClient.RemoteHost?
Не совсем так.
Метод LookupHostAddr это обёртка стандартах функции WinSock: inet_addr() или gethostbyname(). В него вы подставляете всякое (например: 127.0.0.1, localhost, mycomputer, www.ya.ru), а получаете ip адрес в виде "127.0.0.1".
В методе TTcpClient.Open, значение из RemoteHost преобразуется той же inet_addr(). Поэтому, полагаю туда, так же можно подставлять всякое.
Метод LookupHostAddr служит, скорее для каких-нибудь своих прикладных преобразований.
Сказать, какой же в итоге адрес подставляется в bind() или connect(), можно либо трассируя код метода Open, либо косвенными путями. Например, сделав прямое (как это делается в Open) и обратное преобразование адреса: 1) string->TSockAddr c помощью GetSocketAddr() и 2) обратно TSockAddr ->string.
>>>Если да, то как там с быстродействием?
Функции стандартные. В разовом использовании задержек не заметил. Но по-видимому, всё зависит от платформы, потому, как и функционал различается.
На всякий случай уточню. Подразумевается, что через TTcpClient.LookupHostAddr определяем по имени хоста ip-адрес, который и подставляем в TTcpClient.RemoteHost? Если да, то как там с быстродействием? Не будет тормозить?
>>>Можно ли как-то научить сокет понимать имя хоста?
Если речь идёт о компоненте TTcpClient из поставки Delphi, то с помощью методов LookupHostName, LookupHostAddr. А метод LookupPort понимает номер порта в виде строки сервиса (например, "tftp").
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.