Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.09.03;
Скачать: CL | DM;

Вниз

Помогите пожалуйста с проверкой на наличие компа в сети   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.046 c
15-1155063222
Евгений К.
2006-08-08 22:53
2006.09.03
Обмен опытом на практике


15-1155013808
Ega23
2006-08-08 09:10
2006.09.03
С Днём рождения! 8 августа


15-1155158224
Алхимик
2006-08-10 01:17
2006.09.03
Подарок на день рождения


3-1146930148
parovoZZ
2006-05-06 19:42
2006.09.03
Кодировка таблиц


2-1155462921
Triton
2006-08-13 13:55
2006.09.03
Модератор - чудак на букву "М"