Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сканирование лок. сети и поиск программы-сервера по ней


Swimmer ©   (2004-02-13 20:24:00) 

Ув. Мастера, помогите. Принес я преподавателю сетевую программу. В ini-файлах прог-клиентов указываю IP сервера, все отлично работает, мне лично нравится. Но не преподу! Он требует, чтоб клиенты сами искали сервер по всей локалке, как в программах для администрирования клубов! Как сие можно реализовать? Уж очень нужно. Да, лучше всего подошло бы решение с использованием TClientSocket и TServerSocket.


Polevi   (2004-02-17 11:50:00) [1]

>Verg ©   (17.02.04 11:33) [12]
ну будем считать что у нас один интерфейс :)
а вообще можно ручками несколько sendto


Verg   (2004-02-17 11:33:00) [2]


> Polevi ©   (17.02.04 10:00) [11]


> Addr.sin_addr.s_addr := INADDR_BROADCAST;


Вот это немного мутный вопрос.
Если несколько сетевых карт, то куда уйдет такой броадкаст?

BSD-системы делают что - ядро само понимает что ты хочешь отправить всем в сегменте(ах), достает таблицу интерфесов и рассылает в каждую подсеть уже нормальный броадкаст, т.е. на броадкастовые IP адреса всех подсетей (ifaddr_ipv4 | ~ifaddr_subnetmask).

А вот под виндами, тут по-моему, этот номер не пройдет. Пакет отправится на какой-то один сегмент (сетевую карту). На какой?
Я сам толком с этим не разобрался. Почему винды прописывает в маршрутную таблицу путь к INADDR_BROADCAST на какой-то один интерфейс. Главное - я не могу понять почему именно этот она выбирает, а не какой-то другой. Из каких соображений?


Polevi   (2004-02-17 10:00:00) [3]

поток читает UDP пакеты, пришедшие на порт 5555
код не анализирует результат вызова WSAWaitForMultipleEvents, кому надо тот доделает :)


procedure TT.Execute;
var
 Buffer:Pointer;
 Len:integer;
 evt:THandle;
 bytesRecvd:integer;
const
 bufLen=512;
begin
 GetMem(Buffer,bufLen);
 try
   try
     FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     FAddr.sin_family := AF_INET;
     FAddr.sin_addr.s_addr := INADDR_ANY;
     FAddr.sin_port := htons(5555);
     if bind(FSocket, @FAddr, SizeOf(FAddr))=SOCKET_ERROR then
       RaiseLastWin32Error;
     evt:=CreateEvent(nil,false,false,nil);
     WSAEventSelect(FSocket,evt,FD_READ);
     while not Terminated do
     begin
       WSAWaitForMultipleEvents(1,@evt,false,INFINITE,false);
       Len:=sizeof(FAddr);
       ZeroMemory(Buffer,bufLen);
       bytesRecvd:=recvfrom(FSocket,Buffer^,bufLen,0,FAddr,Len);
       if bytesRecvd=SOCKET_ERROR then
         RaiseLastWin32Error;
       //буфер содержит данные, чтото с ними делаем...
     end;
     CloseHandle(evt);
     closesocket(FSocket);
   except
   end;
 finally
   FreeMem(Buffer);
 end;
end;


отправляем в сеть броадкаст пакет по порту 5555

procedure TForm1.Button1Click(Sender: TObject);
var
 ASocket:TSocket;
 Addr: TSockAddrIn;
 Len:integer;
 BroadCast:boolean;
begin
 BroadCast:=true;
 ASocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 setsockopt (ASocket,SOL_SOCKET,SO_BROADCAST,PChar(@BroadCast),sizeof(boolean));
 Addr.sin_family := AF_INET;
 Addr.sin_addr.s_addr := INADDR_BROADCAST;
 Addr.sin_port := htons(5555);
 Len:=sizeof(Addr);
 if sendto(ASocket,PChar('hello world')^,12,0,Addr,Len)=SOCKET_ERROR then
   RaiseLastWin32Error;
 closesocket(ASocket);
end;


да и не забыть про WSAStartup


Alex Konshin   (2004-02-17 09:50:00) [4]

Я это подозревал. Значит, нельзя.


Polevi   (2004-02-17 09:25:00) [5]

он не умеет


Alex Konshin   (2004-02-17 06:42:00) [6]

Я с TClientSocket не работаю. Если он умеет создавать UDP сокеты, то можно, если нет, то нет.


dr Tr0jan   (2004-02-17 06:21:00) [7]

2 Alex Konshin ©   (14.02.04 05:49) [6]:

А как отправить Broadcast запрос, используя TClientSocket?


Alex Konshin   (2004-02-14 05:49:00) [8]

Ничего не надо перебирать. Клиент должен послать broadcast запрос, а сервер - просто на него ответить. Вот так клиент и узнает его адрес.


Так мимо шел   (2004-02-14 05:02:00) [9]

В общих чертах:
порт клиента и сервера одинаковые (иначе никак :) ) отсюда:
1) в диалог сервера с клиентом закладываешь команду, ну допустим
GetStatusMyServer на которую сервер должен ответить StatusServer_Ready
2) в клиенте вкладываешь следующую фичу: перебираешь все станции в сети (на форуме много таких примеров, тема довольно таки избита) определяешь по имени станции ее IP-адрес и посылаешь команду  GetStatusMyServer, если на этой станции твой сервер, то он ответит StatusServer_Ready
и т.д. и т.п. :)


  (2004-02-13 21:26:00) [10]

Удалено модератором


  (2004-02-13 21:26:00) [11]

Удалено модератором


Swimmer   (2004-02-13 21:23:00) [12]

Расскажите как...


Dimaz-z   (2004-02-13 20:58:00) [13]

ClientSocket & ServerSocket тут не подойдут...
используй UDP


Наверх

Титульная страница Поиск, карта сайта Написать письмо