Подскажите, как можно с помощью Indy реализовать следующую фишку. Есть некий
сервер, есть клиенты. Hаходятся они в локальной сети. Клиенты - это некие
устройства, черные ящики с дисплеями, но без клавиатуры (хотя клава может
подключаться для настроек). Хотелось бы сделать так, чтобы при подключении
нового устройстова-клиента он сам бы находил в локалке сервер и подключался к
нему. Сервер отвечает на входящие соединения по порту 5000. Вариант ручной
настройки тоже предусмотрен, но на пожарный случай, если устройство не может
само найти сервер или их более одного. Система должна быть автономной, например,
если сервер ушел в даун (перегрузили или перенесли его функции на другой
компьютер), а потом снова ожил, то клиенты должны автоматом его найти и снова
подключиться.
Есть идея посылать UDP-пакеты для поиска клиентом сервера и сервером для
сообщения о том, что он ожил. Может есть примеры реализации таких вещей?
--
Alexander Grischenko
<gralex(at)ml.lv>
> Есть идея посылать UDP-пакеты для поиска клиентом сервера и сервером
> для сообщения о том, что он ожил. Может есть примеры реализации таких
> вещей?
Попробуем обойтись без INDY
unit net_stuff;
interface
uses Windows, Messages, SysUtils, Classes, Dialogs, WinTypes, WinProcs, WinSock;
const
WINSOCK_VERSION = $0101;
{==============================================================================}
{== Описание типов ============================================================}
{==============================================================================}
type
PNetResourceArray = ^TNetResourceArray;
TNetResourceArray = array[0..MaxInt div SizeOf(TNetResource) - 1] of
TNetResource;
type SERVER_INFO_100 = record
sv100_platform_id : DWORD;
sv100_name : LPWSTR;
end;
PSERVER_INFO_100 = ^SERVER_INFO_100;
LPSERVER_INFO_100 = ^SERVER_INFO_100;
{==============================================================================}
{== Импортируемые функции =====================================================}
{==============================================================================}
function NetApiBufferFree(Buffer: Pointer): DWORD; stdcall; external
'netapi32.dll';
function NetServerEnum(
servername : LPCWSTR;
level : DWORD;
buf : PSERVER_INFO_100;
prefmaxlen : DWORD;
entriesread : LPDWORD;
totalentries : LPDWORD;
servertype : DWORD;
domain : LPCWSTR;
resume_handle : LPDWORD
): DWORD; stdcall; external 'netapi32.dll';
//------------------------------------------------------------------------------
function EnumWorkstations(Server, Domain : string) : TStringList;
function GetIPAddress(name: string): string;
implementation
//-- Получение IP по имени -----------------------------------------------------
function GetIPAddress(name: string): string;
var
WSAData: TWSAData;
p: PHostEnt;
begin
WSAStartup(WINSOCK_VERSION, WSAData);
p := GetHostByName(PChar(name));
Result := inet_ntoa(PInAddr(p.h_addr_list^)^);
WSACleanup;
end;
//-- Список находящихся в сети машин -------------------------------------------
function EnumWorkstations(Server, Domain : string) : TStringList;
var Buffer, tmpBuffer : Pointer;
prefmaxlen : Integer;
resume_handle : DWORD;
entriesread : DWORD;
totalentries : DWORD;
I, Size : Integer;
CompName : string;
PSrvr, Dom : PWideChar;
Begin
Result := TStringList.Create;
Try
Size := Length(Server);
if Size > 0 then begin
GetMem(PSrvr, Size*SizeOf(WideChar)+1);
StringToWideChar(Server, PSrvr, Size+1);
end else PSrvr := nil;
Size := Length(Domain);
if Size > 0 then begin
GetMem(Dom, Size*SizeOf(WideChar)+1);
StringToWideChar(Domain, Dom, Size+1);
end else Dom := nil;
prefmaxlen := -1;
entriesread := 0;
totalentries := 0;
resume_handle := 0;
if NetServerEnum(PSrvr, 100, @Buffer, prefmaxlen, @entriesread,
@totalentries, 1, Dom, @resume_handle) = S_OK
then begin
tmpBuffer := Buffer;
for I := 0 To totalentries - 1 do begin
CompName := PSERVER_INFO_100(tmpBuffer).sv100_name;
resume_handle := 0;
Result.Add(CompName);
tmpBuffer := Pointer(DWORD(tmpBuffer) + SizeOf(SERVER_INFO_100));
end;
end;
finally
NetApiBufferFree(Buffer);
end;
FreeMem(PSrvr);
end;
end.
Таким образом мы получим список машин в сети. А далее любым способом
проверяем - открыт ли нужный порт и идет ли из него правльный ответ. Hапример
- с помощью TClientSocket.
--
Шмырев А. А.
Хмм... пример интересный, спасибо :) , но есть одна загвоздка. Дело в том, что
девайсы работают под управлением Windows XP Embedded, и оттуда исключены все
лишние модули, в том числе и MS Network, т.е. сервисы клиента и сервера там не
работают, только чистый TCP\IP. Hу и, соответсвенно, работают только те сетевые
сервисы, которые я сам запустил, в данном случае только моя прога, которая
должна передавать серверу данные, собираемые устройством. Сам сервер работает на
обычном компе. Сомневаюсь, что предложенный способ поиска машин будет работать в
данном случае...
--
Alexander Grischenko
<gralex(at)ml.lv>
24 окт 07 Alexander Grischenko пишет для Del
AG> Хмм... пpимеp интеpесный, спасибо :) , но есть одна загвоздка. Дело в том,
AG> что девайсы pаботают под упpавлением Windows XP Embedded, и оттуда
AG> исключены все лишние модули, в том числе и MS Network, т.е. сеpвисы
AG> клиента и сеpвеpа там не pаботают, только чистый TCP\IP.
Может тебе в стоpону бpодкастов поглядеть? Почитай о pеализации пpотокола
SAP (service advertisment protocol). А заодно и SLP (service location
protocol).
Общая идея такова: в пеpвом сеpвеp пеpиодически посылает шиpоковещательные
сообщения - мол я такой-то, с такими-то возможностями, клиенты слушают;
во втоpом случае клиент посылает шиpоковещательные запpосы - мол кто тут
занимается тем-то и тем-то, а сеpвеp слушает и откликается.
Так pаботают многие сеpвисы, dhcp напpимеp.
Реализовать, imho, можно обычными сокетами.
Hу пока.
--
В ногах пpавды нет! Она где-то между...