Форум: "Сети";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
ВнизПомогите пожалуйста с проверкой на наличие компа в сети Найти похожие ветки
← →
Jah182100Jah © (2006-03-27 22:58) [0]Люди добрые... поготи хто может, есть такая проблемка, необходимо сканить локальную сетку на наличие компов по ip с получением имени если комп найдет, я использую функцию:
function IPAddrToName(IPAddr: string): string;
var
SockAddrIn: TSockAddrIn;
HostEnt: PHostEnt;
WSAData: TWSAData;
begin
WSAStartup($101, WSAData);
SockAddrIn.sin_addr.s_addr := inet_addr(PChar(IPAddr));
HostEnt := gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET);
if HostEnt <> nil then
Result := StrPas(Hostent^.h_name)
else
Result := "";
end;
Но с ней все делается очччеееенннньььь долго, если сканить всю подсеть то около 20 минут... А хотелось бы побыстрее :)
Кто-нибудь знает как енто обойти???
← →
Eraser © (2006-03-28 00:44) [1]
> Jah182100Jah © (27.03.06 22:58)
так ф-я которую ты привёл совершенно другую задачу выполняет...
Решение - пинговать компы.
← →
Jah182100Jah © (2006-03-28 08:02) [2]Ну насчет того что другую..., енто я согласен, она получает имя компа в сети по ip, но ежели имени нет, то и компа нету (почти всегда :) ), а насчет пингования... если честно я не вкурсе, как это сделать средствами делфи!!!
Ежели подскажешь буду очень благодарен!!!
← →
Alarm © (2006-03-28 10:29) [3]http://www.delphimaster.ru/articles/netmon/index.html
← →
Jah182100Jah © (2006-03-28 10:34) [4]Оооо, спасибо, буду читать... как тока на работе время появится... или до дома придется терпеть))))
← →
diMAN © (2006-03-28 10:35) [5]В своё время я тоже с этим намучился. Вначале пробовал получить имена именно этим способом (через gethostbyaddr). Затем решил посмотреть сниффером как получает имена компьютеров программа Netbios Share Scaner, а делает это она ОЧЕНЬ быстро (255 компов пробегает менее чем за 2 сек. и выдаёт помимо ip и имя машины также MAC и имя залогиненного пользователя, правда последнее не всегда). Так вот эта программа для получения имени посылает netbios-запрос. Разбираться с netbios мне было особо некогда, поэтому я ограничился просто посылкой пакета и приёмом ответа. Но у меня в отличие от Netbios Share Scaner не всегда отображает имена из-за кривизны реализации. Вот мой код, может пригодится, хотя по-правильному нужно писать именно через обращение к netbios.
unit NBTStat;
interface
uses Windows;
type
TMAC = array [1..6] of byte;
PMAC = ^TMAC;
TNBTStat = packed record
ComputerName : String;
GroupName : String;
UserName : String;
MAC : TMAC;
MACAddress : String;
end;
PNBTStat = ^TNBTStat;
function GetNBTStat(lpIPAddress: String; var lpStat: TNBTStat): boolean; overload;
function GetNBTStat(dwIPAddress: DWORD; var lpStat: TNBTStat): boolean; overload;
implementation
uses NetRFC, WinSock, SysUtils;
function WaitForEchoReply(s: TSOCKET): integer;
var
Timeout: timeval;
readfds: Tfdset;
begin
readfds.fd_count := 1;
readfds.fd_array[0] := s;
Timeout.tv_sec := 0;
Timeout.tv_usec := 100;
Result := Select(1, @readfds, nil, nil, @Timeout);
end;
function GetNBTStat(lpIPAddress: String; var lpStat: TNBTStat): boolean;
begin
Result := GetNBTStat(inet_addr(PChar(lpIPAddress)), lpStat);
end;
function GetNBTStat(dwIPAddress: DWORD; var lpStat: TNBTStat): boolean;
var
sockRaw : TSocket;
dest : TSockAddrIn;
from : TSockAddrIn;
netbios : NetBiosHeader;
timeout : integer;
bread : integer;
bwrote : integer;
recvbuf : pointer;
fromlen : integer;
i : integer;
begin
Result := False;
with lpStat do
begin
ComputerName := "";
GroupName := "";
UserName := "";
MACAddress := "";
ZeroMemory(@MAC, SizeOf(MAC));
end;
sockRaw := Socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
ZeroMemory(@dest, SizeOf(dest));
with dest do
begin
sin_family := AF_INET;
sin_port := htons(137);
sin_addr.S_addr := dwIPAddress;
end;
ZeroMemory(@netbios, SizeOf(netbios));
with netbios do
begin
TrID := htons($29);
Flags := htons($10);
Questions := htons($01);
AnswerRRs := 0;
AuthorityRRs := 0;
AdditionalRRs := 0;
FillChar(Queries_Name, 34, #$41); // $20 $43 $4b $41 ... $00; bytes 34
Queries_Name[1] := $20;
Queries_Name[2] := $43;
Queries_Name[3] := $4b;
Queries_Name[34] := $00;
Queries_Type := htons($21); // NBSTAT
Queries_Class := htons($01); // INET
end;
{
timeout := 1;
bread := SetSockOpt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, PChar(@timeout), SizeOf(timeout));
if bread = SOCKET_ERROR then Exit;
timeout := 1;
bread := SetSockOpt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, PChar(@timeout), SizeOf(timeout));
if bread = SOCKET_ERROR then Exit;
}
bwrote := SendTo(sockRaw, netbios, SizeOf(netbios), 0, dest, SizeOf(dest));
if bwrote = SOCKET_ERROR then Exit;
bread := WaitForEchoReply(sockRaw);
if (bread = SOCKET_ERROR) or (bread = 0) then Exit;
GetMem(recvbuf, MAX_PACKET);
ZeroMemory(recvbuf, MAX_PACKET);
fromlen := SizeOf(from);
bread := RecvFrom(sockRaw, recvbuf^, MAX_PACKET, 0, from, fromlen);
if bread = SOCKET_ERROR
then begin
FreeMem(recvbuf);
Exit;
end;
with NetBios_NameService_Responce(recvbuf^), lpStat do
begin
ComputerName := String(Answer_Name1);
for i := 1 to Answer_NumOfNames - 1 do
begin
if (Names[i].NameType = 0) and (Names[i].NameFlags = $44)
then GroupName := String(Names[i].Name);
if (Names[i].NameType = 3) {and (Names[i].NameFlags = $44)}
then UserName := String(Names[i].Name);
end;
MAC := PMAC(@Names[Answer_NumOfNames].Name)^;
MACAddress := Format("%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", [MAC[1], MAC[2], MAC[3], MAC[4], MAC[5], MAC[6]]);
end;
FreeMem(recvbuf);
Result := True;
end;
end.
← →
Rouse_ © (2006-03-28 10:36) [6]Тут лучше чуть урезанную версию вот этого кода использовать:
http://rouse.front.ru/fastscan.zip
Просто в коде отключить сканирование ресурсов и делать завершение потока при нахождении имени ресурса...
← →
diMAN © (2006-03-28 10:45) [7]Да, вот ещё, забыл
unit NetRFC;
interface
type
NetBiosHeader = packed record
TrID : word;
Flags : word;
Questions : word;
AnswerRRs : word;
AuthorityRRs : word;
AdditionalRRs : word;
Queries_Name : array [1..34] of byte;
Queries_Type : word;
Queries_Class : word;
end;
NBName = packed record
NameFlags : word;
Name : array [1..15] of char;
NameType : byte;
end;
NetBios_NameService_Responce = packed record
TrID : word;
Flags : word;
Questions : word;
AnswerRRs : word;
AuthorityRRs : word;
AdditionalRRs : word;
Answer_Name : array [1..34] of byte;
Answer_Type : word;
Answer_Class : word;
Answer_TTL : dword;
Answer_DataLenght : word;
Answer_NumOfNames : byte;
Answer_Name1 : array [1..15] of char;
Answer_Name1Type : byte;
Names : array [1..1] of NBName;
end;
implementation
end.
← →
Jah182100Jah © (2006-03-28 12:57) [8]Всем откликнувшимся на мою проблему ОГРОМНОЕ спасибо... будет чем заняться вечерком))), надеюсь получится... об результате обязуюсь отписаться)))
← →
EarlVadim © (2006-04-19 09:47) [9]Rouse_ прислал великолепный работающий образец сканера по IP.
У меня несколько другая проблема.
У меня есть список сетевых имен компьютеров, а не их IP.
Как в этом случае быстро узнать, какие из них в данный момент работают?
← →
Rouse_ © (2006-04-19 10:20) [10]
> Как в этом случае быстро узнать, какие из них в данный момент
> работают?
Получить IP каждого компьютера через gethostbyname и по аналогии...
← →
EarlVadim © (2006-04-19 10:32) [11]щас попробую, но в любом случае - спасибо... :beer:
← →
Чапаев © (2006-04-19 12:38) [12]
> WSAStartup($101, WSAData);
1. Зачем это делать внутри функции?
2. А WsaCleanup() вызывать Пушкин будет?
← →
EarlVadim © (2006-04-19 17:01) [13]2Rouse_
Там все ещё проще оказалось.
Достаточно
For i:= 1 to HOSTCount do BEGIN
EXIST[i]:= false;
if NetShareEnum(StringToOleStr(NAME[i]), 1, Info, DWORD(-1), @entriesread,
@totalentries, nil) = 0 then
try
if entriesread > 0 then EXIST[i]:= true;
finally
NetApiBufferFree(Info);
end;
END;
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.053 c