-
Столько лет нормально работала функция NetBIOS. Получал с помощью нее MAC-адреса хостов. Очень незаменимая вещь — может вернуть MAC хоста за маршрутизатором (если протокол разрешен NETBIOS). И тут на-те! MS оказывается прекратила ее поддержку начиная с Висты! http://msdn.microsoft.com/en-us/library/bb870903%28VS.85%29.aspx..."[Netbios is not supported on Windows Vista, Windows Server 2008, and subsequent versions of the operating system]"... Я потратил несколько месяцев на понимание, отчего моя прога вдруг начала непредсказуемо глючить в ходе выполнения этой функции именно в Висте и 7ке. Память сильно портилась, ломались указатели в разных местах... Как следствие — исключения, приводящие к завершению. Перепробовал кучу примеров из инета по использованию ее. Полез в оффлан-мсдн — там даже описания нет ее. И наконец полез в онлайн-мсдн, и сделал печальное открытие. Какие комментарии, товарищи разработчики? Как дальше жить без нее? Может замена какая есть, а я не знаю просто? Самое интересное, что если хост существует, то функция нормально отрабатывает и возвращает MAC. Иначе — глюки с памятью после вызова: то цикл от i=0 to 0 вдруг становится бесконечным, то объекты созданные до вызова NetBIOS перестают нормально существовать.
-
> Иначе — глюки с памятью после вызова: то цикл от i=0 to > 0 вдруг становится бесконечным, то объекты созданные до > вызова NetBIOS перестают нормально существовать.
По моему у тебя в программе ошибка.
-
> По моему у тебя в программе ошибка.
В 5й строке? :)
-
Вот, ребята с другого форума подсказали, как реализовать замену функции NetBIOS. Просто отправить нужный NBQuery по UDP хосту, MAC которого нужно узнать. Замечательно работает в случае, если хост включен и работает netbios на нем. Иначе обычный выход по таймауту при select. Никаких заморочек, как в случае с функцией NetBIOS.
const
NB_QUERY : array[0..37] of Byte = ($20,$43,$4b,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41 ,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$41,$00,$00,$21,$00,$01);
type
PMacAddress = ^TMacAddress;
TMacAddress = array[0..5] of byte;
type
PNB_HEADER = ^NB_HEADER;
NB_HEADER = packed record
wTransId : Word;
wFlags : Word;
wQuestions : Word;
wAnswerRRs : Word;
wAuthRRs : Word;
wAdditionalRRs : Word;
end;
type
PNB_NAME = ^NB_NAME;
NB_NAME = packed record
Name : array[0..15] of char;
Flags : Word;
end;
type
PNB_ANSWER = ^NB_ANSWER;
NB_ANSWER = packed record
RRName : array[0..33] of char;
Nbtype : Word;
Nbclass : Word;
dwTTL : DWord;
wDataLen : Word;
NumNames : Byte;
end;
.................
function GetMACAddrUDP(hostaddr: string; var mac: string): boolean;
var
S: TSocket;
AddrSize, Return: Integer;
Header: NB_HEADER;
Target: TSockAddrIn;
P: Pointer;
OrigTransId: Word;
TimeOut: TTimeVal;
FDSet: TFDSet;
Buffer: array[0..$800] of Byte;
NumNames, Offset: Integer;
MA: TMacAddress;
begin
mac := '';
Result := False;
s := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
try
OrigTransId := LoWord(GetTickCount);
ZeroMemory(@Header, SizeOf(Header));
Header.wTransId := OrigTransId;
Header.wFlags := $1000;
Header.wQuestions := htons(1);
ZeroMemory(@Target, SizeOf(Target));
Target.sin_family := AF_INET;
Target.sin_addr.S_addr := inet_addr(Pchar(hostaddr));
Target.sin_port := htons(137);
GetMem(P, SizeOf(Header) + SizeOf(NB_QUERY));
try
ZeroMemory(P, SizeOf(Header) + SizeOf(NB_QUERY));
MoveMemory(P, @Header, SizeOf(Header));
MoveMemory(Ptr(DWORD(P) + SizeOf(Header)), @NB_QUERY, SizeOf(NB_QUERY));
if sendto(s, P^, SizeOf(Header) + SizeOf(NB_QUERY), 0, Target, SizeOf(Target)) <> SOCKET_ERROR then
begin
ZeroMemory(@FDSet, SizeOf(FDSet));
FDSet.fd_array[0] := S;
FDSet.fd_count := 1;
ZeroMemory(@TimeOut, SizeOf(TimeOut));
TimeOut.tv_sec := 1;
if select(0, @FDSet, nil, nil, @TimeOut) > 0 then
begin
ZeroMemory(@Buffer, SizeOf(Buffer));
AddrSize := SizeOf(Target);
Return := recvfrom(s, Buffer, SizeOf(Buffer), 0, Target, AddrSize);
if Return > SizeOf(Header) then
begin
with PNB_HEADER(@Buffer)^ do
if (OrigTransId = wTransId) and ((wFlags shr 12) = 0) and (htons(wAnswerRRs) = 1) then
begin
NumNames := PNB_ANSWER(Ptr(DWord(@Buffer) + SizeOf(NB_HEADER)))^.NumNames;
if NumNames * SizeOf(NB_NAME) + SizeOf(TMacAddress) < (Return - SizeOf(NB_HEADER)) then
begin
Offset := SizeOf(NB_HEADER) + SizeOf(NB_ANSWER) + NumNames * SizeOf(NB_NAME);
MA := PMacAddress(Ptr(Integer(@Buffer) + Offset))^;
mac := IntToHex(MA[0], 2);
mac := mac + '-' + IntToHex(MA[1], 2);
mac := mac + '-' + IntToHex(MA[2], 2);
mac := mac + '-' + IntToHex(MA[3], 2);
mac := mac + '-' + IntToHex(MA[4], 2);
mac := mac + '-' + IntToHex(MA[5], 2);
Result := True;
end;
end;
end;
end;
end;
finally
FreeMem(P);
end;
finally
closesocket(S);
end;
end;
|