Обзор имен компьютеров в сети

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
ru_alex
Ветеран
Сообщения: 333
Зарегистрирован: 21 Сентябрь 2005, 11:05
Откуда: Нижний Новгород
Контактная информация:

Обзор имен компьютеров в сети

Сообщение ru_alex »

А кто-нибудь знает функцию (или может несколько функций) для обзора имен компьютеров в сети.
Пробую встроить в программу "Чат" через сокеты, и хотелось бы автоматически искать по сети тех, кто сейчас находится в программе...
Аватара пользователя
Admin
Администратор
Сообщения: 4010
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 53 раза
Поблагодарили: 33 раза
Контактная информация:

Сообщение Admin »

Вопрос 2 StillZero
softcreator
Ветеран движения
Сообщения: 78
Зарегистрирован: 04 Август 2005, 9:35
Контактная информация:

Сообщение softcreator »

вообще-то это вопрос к MSDN :)
http://msdn.microsoft.com/library/defau ... ources.asp
Аватара пользователя
Admin
Администратор
Сообщения: 4010
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 53 раза
Поблагодарили: 33 раза
Контактная информация:

Сообщение Admin »

Молодец! :)
Просто Андрей помнится недавно чем то подобным занимался и может быть исходники остались...
Если что есть попрошу завтра на работе написать сюда.
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

Вадим, вообщем-то, показал пример обзора компьютеров в сети. Хотя, по сути, это для организации красивого выбора имени компа, можно и руками набрать там \\MyCompName.
IMHO хороший подход: есть список компов, на которых стоит стоит прога, а запущена ли на них прога уже опрашивать потом. Т.е. не делать BROADCAST по всей сети, а зная имена компов и соответственно их адреса, просто опрашивать их командами по TCP типо "ONLINE?" в ответку "ONLINE!" или ошибка.

Как сделать BROADCAST можно посмотреть здесь (делается это по UDP): http://www.clarionlife.net/cgi-bin//bl_ ... senger.zip

Вообще, можно сделать и без использования всяких API: общий файл, каждому компу своя запись, зашел в прогу: выставил байтик, вышел: снял, и периодически должа прога снимать/выставлять активность (если юзер вышел по "reset"-например). Ну и кнопочка refresh должна быть, которая сбрасывает у всех байтик.
ru_alex
Ветеран
Сообщения: 333
Зарегистрирован: 21 Сентябрь 2005, 11:05
Откуда: Нижний Новгород
Контактная информация:

Сообщение ru_alex »

По ссылке http://msdn.microsoft.com/library/defau ... ources.asp, приведенной выше, пример функции для обзора ресурсов сети:

Код: Выделить всё

BOOL WINAPI EnumerateFunc(HWND hwnd, 
                          HDC hdc, 
                          LPNETRESOURCE lpnr)
{ 
  DWORD dwResult, dwResultEnum;
  HANDLE hEnum;
  DWORD cbBuffer = 16384;      // 16K is a good size
  DWORD cEntries = -1;         // enumerate all possible entries
  LPNETRESOURCE lpnrLocal;     // pointer to enumerated structures
  DWORD i;
  //
  // Call the WNetOpenEnum function to begin the enumeration.
  //
  dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, // all network resources
                          RESOURCETYPE_ANY,   // all resources
                          0,        // enumerate all resources
                          lpnr,     // NULL first time the function is called
                          &hEnum);  // handle to the resource

  if (dwResult != NO_ERROR)
  {  
    //
    // Process errors with an application-defined error handler.
    //
    NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetOpenEnum");
    return FALSE;
  }
  //
  // Call the GlobalAlloc function to allocate resources.
  //
  lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
  if (lpnrLocal == NULL) 
      return FALSE;
  
  do
  {  
    //
    // Initialize the buffer.
    //
    ZeroMemory(lpnrLocal, cbBuffer);
    //
    // Call the WNetEnumResource function to continue
    //  the enumeration.
    //
    dwResultEnum = WNetEnumResource(hEnum,      // resource handle
                                    &cEntries,  // defined locally as -1
                                    lpnrLocal,  // LPNETRESOURCE
                                    &cbBuffer); // buffer size
    //
    // If the call succeeds, loop through the structures.
    //
    if (dwResultEnum == NO_ERROR)
    {
      for(i = 0; i < cEntries; i++)
      {
        // Call an application-defined function to
        //  display the contents of the NETRESOURCE structures.
        //
        DisplayStruct(hdc, &lpnrLocal[i]);

        // If the NETRESOURCE structure represents a container resource, 
        //  call the EnumerateFunc function recursively.

        if(RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage
                                       & RESOURCEUSAGE_CONTAINER))
          if(!EnumerateFunc(hwnd, hdc, &lpnrLocal[i]))
            TextOut(hdc, 10, 10, "EnumerateFunc returned FALSE.", 29);
      }
    }
    // Process errors.
    //
    else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
    {
      NetErrorHandler(hwnd, dwResultEnum, (LPSTR)"WNetEnumResource");
      break;
    }
  }
  //
  // End do.
  //
  while(dwResultEnum != ERROR_NO_MORE_ITEMS);
  //
  // Call the GlobalFree function to free the memory.
  //
  GlobalFree((HGLOBAL)lpnrLocal);
  //
  // Call WNetCloseEnum to end the enumeration.
  //
  dwResult = WNetCloseEnum(hEnum);
  
  if(dwResult != NO_ERROR)
  { 
    //
    // Process errors.
    //
    NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetCloseEnum");
    return FALSE;
  }

  return TRUE;
}

Попробовал реализовать на Clarion, нужно получать имена компов для опроса запущена прога или нет. Использовать BROADCAST, реализованный в Messenger, не хочу. Гляньте, у кого есть время, целесообразен ли такой вариант и будет ли поддерживаться на разных вариантах настройки сети. У меня одна рабочая группа и порядка 20 машин, все ок.

Код на Clarion:

Код: Выделить всё


ERROR_NO_MORE_ITEMS     EQUATE(259)
RESOURCE_CONNECTED      EQUATE(1)
RESOURCE_GLOBALNET      EQUATE(2)
RESOURCE_REMEMBERED     EQUATE(3)
RESOURCETYPE_ANY        EQUATE(0)
RESOURCETYPE_DISK       EQUATE(1)
RESOURCETYPE_PRINT      EQUATE(2)
RESOURCEDISPLAYTYPE_GENERIC  EQUATE(0)
RESOURCEDISPLAYTYPE_DOMAIN   EQUATE(1)
RESOURCEDISPLAYTYPE_SERVER   EQUATE(2)
RESOURCEDISPLAYTYPE_SHARE    EQUATE(3)
RESOURCEUSAGE_CONTAINER EQUATE(2)

NETRESOURCE             GROUP,TYPE
dwScope                   ULONG
dwType                    ULONG
dwDisplayType             ULONG
dwUsage                   ULONG
lpLocalName               LONG
lpRemoteName              LONG
lpComment                 LONG
lpProvider                LONG
                        END

     MODULE('Mpr.lib')
       WNetOpenEnum(ULONG,ULONG,ULONG,LONG,HANDLE),ULONG,PASCAL,NAME('WNetOpenEnumA'),DLL(dll_mode)
       WNetCloseEnum(HANDLE),ULONG,PASCAL,NAME('WNetCloseEnum'),DLL(dll_mode)
       WNetEnumResource(HANDLE,*ULONG,LONG,*ULONG),ULONG,PASCAL,NAME('WNetEnumResourceA'),DLL(dll_mode)
     END


GetNetRes_ procedure(*NETRESOURCE lpnr)
lpnr1        group(NETRESOURCE),DIM(100)
             end
lpnr2        group(NETRESOURCE)
             end
hEnum        long
cEntries     ulong(-1)
cEntries_    ulong
cbBuffer     ulong(105600)
nResult      long
I            long
strname      cstring(260)
loc:error_   string(500)
 code
 !stop(size(lpnr1))
 loc:error_=''
 nResult = WNetOpenEnum(RESOURCE_GLOBALNET,RESOURCETYPE_ANY,0,address(lpnr),address(hEnum))
 if nResult = 0
   clear(lpnr1)
   nResult = WNetEnumResource(hEnum,cEntries,address(lpnr1),cbBuffer)
   if nResult = 0
     if cEntries<=200
       cEntries_ = cEntries
     else
       cEntries_ = 200
     end
     loop I=1 to cEntries_
       if lpnr1[I].lpRemoteName and lpnr1[I].dwDisplayType=RESOURCEDISPLAYTYPE_SERVER
         peek(lpnr1[I].lpRemoteName,strname)

         stop(strname)


       end
       if RESOURCEUSAGE_CONTAINER = band(lpnr1[I].dwUsage,RESOURCEUSAGE_CONTAINER)
         lpnr2 = lpnr1[I]
         loc:error_=GetNetRes_(lpnr2)
         if clip(loc:error_)
           nResult = WNetCloseEnum(hEnum)
           return(clip(loc:error_))
         end
       end
     end
   elsif nResult = ERROR_NO_MORE_ITEMS
     !stop('Error  WNetEnumResource ERROR_NO_MORE_ITEMS '&nResult)
   else
     loc:error_ = 'Error  WNetEnumResource '&nResult
   end
   nResult = WNetCloseEnum(hEnum)
 else                                                    
   loc:error_ = 'Error  WNetOpenEnum '&nResult
 end
 return(clip(loc:error_))
PS: Динамически создать массив структур NETRESOURCE не получилось, поэтому использую размерность 100
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

целесообразен ли такой вариант и будет ли поддерживаться на разных вариантах настройки сети
у меня этот код не работает: GPF-ит, не разбирался почему
сетка большая: Microsoft + Netware, компов более 200, группы тоже есть конечно :)

в свое время я уже делал подобный "обзор" компьютеров, на моей сетке ОЧЕНЬ ТОРМОЗИТ, поэтому не рекомендую

IMO, как надо:

1. Должна быть таблица - список пользователей
2. Действие: "добавить пользователя" - выбирается имя компа обычным диалогом выбора компьютера
3. Действие: "поиск пользователей" - здесь можно разослать broadcast (разово) по всем машинам и получить отклики либо сделать "обзор" вышеописанным способом
4. Далее список юзеров проверяется по таймеру на активность/неактивность
Аватара пользователя
Олег
Ветеран движения
Сообщения: 122
Зарегистрирован: 16 Июль 2005, 2:35
Откуда: Москва
Контактная информация:

Сообщение Олег »

Это не есть хороший вариант!
Если прога упадет, то данный экземпляр так и останется активным в вашей таблице!
Самый простой, и надежный (проверено на больших сетках в течении нескольких лет) вариант я уже как-то описывал.
Основной принцип - в каталоге БД выделяется некий каталог, в котором КАЖДЫЙ экземпляр проги, которая работает с этой БД, имеет свой "почтовый ящик" - небольшой файл с номером данного экземпляра программы. У меня это сделано автоматом - при запуске прога смотрит в INI-файл - есть там ее номер или нет. Если нет, то заходит в каталог почтовых ящиков и создает список имеющихся там файлов. Файлы имеют имя типа WKS.001 (до тысячи экземпляров)
Ищет максимальный номер и присваивает себе новый номер.
Далее - при запуске экземпляра проги ее почтовый ящик открывается в SHARE-режиме. При этом туда записывается инфа о сетевом имени компа, пользователе (компа и проги) и прочие локальные параметры. Если необходимо создать список экземпляров проги, которые работают в данный момент с БД, то сканируем все файлы - почтовые ящики и пытаемся каждый открыть в монопольном режиме. Если не удалось, то прога, связанная с данным почтовым ящиком, в данный момент работает. Открываем этот файл в SHARE-режиме и читаем из него всю необходимую инфу как о станции, так и о пользователе и локальных настройках. Можно дае оставить в этом файле сообщение для данной проги - если в проге включено сканирование почтового ящика по таймеру, то это сообщение будет считано и показано юзеру.
Основное преимущество данного метода - если прога "вылетела", то операционка сама тут-же закроет файл - почтовый ящик! И сканирование покажет, что данный файл закрыт, а значит прога, связанная с данным почтовым ящиком, неактивна!
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

Если прога упадет, то данный экземпляр так и останется активным в вашей таблице!
неа, так как:
4. Далее список юзеров проверяется по таймеру на активность/неактивность
Ответить