![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск серверов в LAN [D7, Win2k]
seregin2 © (2004-03-01 08:07:00)Здравствуйте, Мастера! С наступлением весны!
Как реализовать средствами Delphi (TClientSocket и TServerSocket) поиск серверов, аналогичный тому, как Quake ищет запущенные сервера мультиплееры. Можно, конечно, сканировать диапазон IP-адресов, но это медленно. Или Quake так и делает?
ser_ega (2004-03-02 00:19:00) [1]>>>> tButton можно, как вариант, получить список компов в сети и про сканировать их.
А примерчик можно как получить список компов в сети?
Verg (2004-03-01 22:45:00) [2]Мдя.
Сам сейчас посмотрел еще раз исходник того сканера. Надо сказать есть масса претензий. Если автор слышит, то предлагаю его заменить на:
function FindServer( const Network : string;
const NetMask : string;
Port : word;
TimeOut : integer) : string;
var
Addr:TSockAddr;
Fd : PFdSet;
k, i: u_long;
TmVal:TTimeVal;
StartAddr,
FinishAddr,
Mask : u_long;
SetSize : integer;
S : TSocket;
begin
Result := '';
StartAddr := ntohl(inet_addr(pchar(Network)));
Mask := ntohl(inet_addr(pchar(NetMask)));
if Mask <> u_long($FFFFFFFF) then
begin
StartAddr := (StartAddr and Mask) + 1;
FinishAddr := (StartAddr or not Mask) - 1;
end else
FinishAddr := StartAddr;
SetSize := (FinishAddr - StartAddr) + 1;
if SetSize <= 0 then
exit;
TmVal.tv_sec:=TimeOut;
TmVal.tv_usec:=0;
GetMem(Fd, SetSize*sizeof(Fd^.fd_array[0])+sizeof(Fd^.fd_count));
try
FD_ZERO(Fd^);
ZeroMemory(@Addr, sizeof(Addr));
Addr.sin_family:=AF_INET;
Addr.sin_port:=htons(Port);
k:=1;
For i:=StartAddr to FinishAddr do
begin
Addr.sin_addr.S_addr:=htonl(i);
S := socket(AF_INET, SOCK_STREAM, 0);
if (S <> INVALID_SOCKET) then
begin
if (ioctlsocket(S, FIONBIO, k) = SOCKET_ERROR)
or ( (connect(S, Addr, SizeOf(Addr)) = SOCKET_ERROR)
and (WSAGetLastError <> WSAEWOULDBLOCK)
) then
begin
closesocket( S );
end else
begin
FD.fd_array[FD^.fd_count] := S;
Inc(FD^.fd_count);
end;
end;
end;
if Fd^.fd_count = 0 then
exit;
select(FD^.fd_count, nil, Fd, nil, @TmVal);
For K := 0 to Fd^.fd_count-1 do
begin
if (Result='')
and FD_ISSET( FD^.fd_array[K], Fd^ ) then
begin
I := sizeof(Addr);
if getpeername( FD^.fd_array[K], Addr, I ) <> SOCKET_ERROR then
Result := inet_ntoa(Addr.sin_addr);
end;
closesocket(FD^.fd_array[K]);
end;
finally
FreeMem(Fd);
end;
end;
Главная фишка - FD_SETSIZE. Как его переопределить-то? Это ж нам не C...
А то, ведь, только первые 64-ре адреса проверяться будут
Возражения?
TButton (2004-03-01 21:56:00) [3]можно, как вариант, получить список компов в сети и про сканировать их.
Verg (2004-03-01 13:27:00) [4]
> Можно, конечно, сканировать диапазон IP-адресов, но это
> медленно.
Если речь идет в общем случае о TCP/IP серверах, то сканирование - это универсальное решение.
Только TClientSocket в данном случае использовать будет нерационально.
Для поиска сервер лучше использовать WinSock API сокеты в неблокирующем режиме. Время поиска сервера, если он вообще есть, будет ~равно времени одного соединения.
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1076919117&n=4
just me (2004-03-01 13:18:00) [5]Посмотри в MSDN функцию NetServerEnum - может решит твою проблему более просто
BiN (2004-03-01 13:18:00) [6]Можно!
seregin2 (2004-03-01 08:59:00) [7]а как-нибудь использовать широковещательные запросы можно?