Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Процедура дозвона модема

9.5K
20 декабря 2006 года
Borgir
97 / / 20.12.2006
День добрый!

Хотелось бы узнать у тех кто это делал одну деталь. Мне примеры кода не обязательны, просто хочу понять логику. Есть модем, я в программе при нажатии кнопки посылаю в СОМ-порт команду дозвона и... не знаю как лучше делать дальше. Дело в том, что после посылки команды дозвона по номеру, модем начинает дозваниваться, затем они начинают с модемом на том конце пересвистываться и только потом, модем отвечает в СОМ-порт "CONNECT". Все это время программа должна как-то ждать этого события. Если я сделаю бесконечный цикл, условием выхода из которого будет приход сообщения от модема, то программа по-сути практически "подвиснет" пока не придет ответ от модема. Это не есть выход.
И еще я не хочу вешать действия, которые надо выполнить после дозвона, на событие СОМ-порта "приход данных", так как из разных процедур программы мне может понадобиться дозваниваться, поэтому и действия, выполняемые после дозвона, могут быть разными.
Подскажите логику реализации процедуры дозвона.

P.S. если че, то программирую на С++Builder
12K
20 декабря 2006 года
wedmed
32 / / 10.12.2006
Цитата: Borgir
День добрый!

Все это время программа должна как-то ждать этого события. Если я сделаю бесконечный цикл, условием выхода из которого будет приход сообщения от модема, то программа по-сути практически "подвиснет" пока не придет ответ от модема.


Честно говоря мне лично не доводилось писать процедуры обработки для подобных дивайсов, но ответ по логике дозвона напрашивается сам собой: существует 2 способа обмена данными между устройствами- синхронный и асинхронный(по-моему это объясняют во всех технических вузах нашей НЕОБЪЯТНОЙ где-то на 2-ом курсе:) ). При синхронном способе происходит примерно то, что ты пытаешься сделать- программа ждёт ответа от устройства и пока его не получит- бездействует.Во втором- данные буфиризируются и обмен начинается по свистку SYNC (-Дорогая, я готов, сделать тебе предложение.- Ну неужели, дорогой...давай!)
Ешё раз оговорюсь, что самому мне такие дивайсы описывать пока не приходилось, но если у тебя нет времени ждать пока кто-нить не напишет подробный код, советую минут сорок пошерстить интернет в поисках документации протоколов передачи данных(в твоём случае RS-232)
P.S.
... Да, ещё можно по диагонали просмотреть учебники по Ассемлеру или по любому популярному сетевому языку программирования(PERL-лучше всего). Там такие вопрсы подробно рассматриваются

9.5K
21 декабря 2006 года
Borgir
97 / / 20.12.2006
На счет режимов обмена я в курсе :)
меня интересует именно этот режим ожидания "свистка SYNC" - как его реализовать? Получается что есть процедура ну например обработки нажатия кнопки. В ней я посылаю модему команды "звонить" и модем начинает звонить. А в процедуре-то что делать, пока модем звонит, как реализовать ожидание ответа от модема ("Дозвонился", "Занято" и тд.)? Еще раз повторюсь, но если сделать бесконченый цикл с постоянной проверкой наличия ответа от модема, то программа практически "подвиснет" пока модем не ответит. А это не очень хорошо.
Если бы существовала всего одна такая процедура, откуда требуется звонить, то я бы голову не ломал, а повесил отсальную часть процедуры (ту что должна выполняться уже после соединения модема) на обработку события СОМ-порта "пришли данные". Но таких процедур в программе много. Единственное что мне пока приходит в голову, это в каждой процедуре записывать например в Тег какого-нибудь компонента разную цифру, и тогда обработчик события "пришли данные" СОМ-порта сможет различать из какой именно процедуры его запустили, и соответственно выполнять разные действия после соединения.
Но что-то мне это кажется некрасиво как-то, кривовато :)
18K
21 декабря 2006 года
dave
35 / / 12.12.2006
RasDial / RasHangUp :)
или вообще обрисуйте задачу что вам надо делать после дозвона
9.5K
21 декабря 2006 года
Borgir
97 / / 20.12.2006
После дозвона надо работать с устройством через СОМ-порт. Напрямую через СОМ-порт моя программа устройство опрашивает без проблем, через модем тоже опрашивает (пробовал вручную программой соеденить модемы и опросить их). Осталось только теперь автоматизировать процесс дозвона.
1
23 декабря 2006 года
kot_
7.3K / / 20.01.2000
Цитата: Borgir
Но таких процедур в программе много. Единственное что мне пока приходит в голову, это в каждой процедуре записывать например в Тег какого-нибудь компонента разную цифру, и тогда обработчик события "пришли данные" СОМ-порта сможет различать из какой именно процедуры его запустили, и соответственно выполнять разные действия после соединения.
Но что-то мне это кажется некрасиво как-то, кривовато :)


А использовать отдельный поток что мешает? И в нем собственно и обрабатывать все события модема, а в параметры потока передавать то что необходимо.
Кстати, эта хренотень будет работать только под Вынь95/98 - под нормальную операционку надо или пользовать РАС-функции или писать драйвер устройства.

9.5K
24 декабря 2006 года
Borgir
97 / / 20.12.2006
На счет отдельного потока, у меня была мысль, но к своему великому стыду, я пока еще не умею работать с потоками, и разбираться некогда.

Далее, какую хренотень ты имеешь в виду, что она будет работать только под Вынь98? Сейчас у меня все прекрасно работает под ХР (процедура дозвона вручную, а затем опрос устройства через СОМ-порт.

На счет РАС-функций, я чесно говоря тоже только слышал :)
А драйвера устройства писать совершенно не к чему. Меня волнует не опрос устройства, а именно дозвон. Конечно можно поставить стандартные драйвера модема и использовать TAPI, но дело в том что программку планируется в дальнейшем продавать вместе с модемами (кстати GSM-модем), и хотелось бы чтобы юзеры просто ставили программу, втыкали модем и все.
И кстати, раз разговор зашел о TAPI, у меня есть компоненты для работы через TAPI, называется APRO, там все великолепно работает с драйверами модема, а почему-то напрямую с СОМ-портом ругается.

З.Ы. Вобщем если до нового года никто не посоветует чего хорошего, придется делать абы как, лишь бы работало :(
1
24 декабря 2006 года
kot_
7.3K / / 20.01.2000
Цитата: Borgir
На счет отдельного потока, у меня была мысль, но к своему великому стыду, я пока еще не умею работать с потоками, и разбираться некогда.

Далее, какую хренотень ты имеешь в виду, что она будет работать только под Вынь98? Сейчас у меня все прекрасно работает под ХР (процедура дозвона вручную, а затем опрос устройства через СОМ-порт.

На счет РАС-функций, я чесно говоря тоже только слышал :)
А драйвера устройства писать совершенно не к чему. Меня волнует не опрос устройства, а именно дозвон. Конечно можно поставить стандартные драйвера модема и использовать TAPI, но дело в том что программку планируется в дальнейшем продавать вместе с модемами (кстати GSM-модем), и хотелось бы чтобы юзеры просто ставили программу, втыкали модем и все.
И кстати, раз разговор зашел о TAPI, у меня есть компоненты для работы через TAPI, называется APRO, там все великолепно работает с драйверами модема, а почему-то напрямую с СОМ-портом ругается.

З.Ы. Вобщем если до нового года никто не посоветует чего хорошего, придется делать абы как, лишь бы работало :(



Попробуй так, часть кода которая к собственно к дозвону отношения не имеет я убрал - при желании можно просто создавать новое соединение дозваниваться а затем удалять. Вобщем - читай МСДН по указанным функциям.

Код:
//Функция обработки сообщений из порта
VOID WINAPI RasCallback(HRASCONN hrasconn, UINT unMsg,
  RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError)
{
  String S = "";
  if (dwError) {
    // Ашибка.
    char buff[256];
    fRasGetErrorString(dwError, buff, sizeof(buff));
    fmMainFtp->LogEvents(buff);
    String MsgError = "При подключении произошла следующая ошибка:\n"+String(buff);
    if(Application->MessageBoxA(MsgError.c_str(),"Ошибка",MB_ICONQUESTION+MB_OKCANCEL)==IDOK){
      fRasHangUp(hrasconn);
     fmMainFtp->ttTimer->Enabled = true;
     return;
    }
    else fmMainFtp->Close();
    return;
  }
  switch (rascs) {
    // Отображение текущего статуса
    case RASCS_PortOpened :
      S = "Открытие порта..."; break;
    case RASCS_DeviceConnected :
      S = "Соединение..."; break;
    case RASCS_Authenticate :
      S = "Вход в сеть..."; break;
    case RASCS_Authenticated :
      S = "Проверка пользователя и пароля"; break;
    case RASCS_Connected : {
      S = "Вход в сеть";
     fmMainFtp->ttTimerClick->Enabled = true;
      break;
    }
    case RASCS_Disconnected :
      S = "Disconnected"; break;
  }
   if (S != "")
    fmMainFtp->LogEvents(S);
}

void __fastcall TfmMainFtp::FormCreate(TObject *Sender)
{
First = 0;
MutexFirst = CreateMutex(NULL,true,"MyMutex");
int Res = GetLastError();
if(Res==ERROR_ALREADY_EXISTS){
First = 1;
 Close();
}
  hRas = 0;
  hRasInstance = LoadLibrary("RASAPI32.DLL");
  if (!hRasInstance) {
    LogEvents("Unable to load RAS DLL.");
    Close();
    return;
  }
  fRasGetErrorString = (pRasGetErrorString)
    GetProcAddress(hRasInstance, "RasGetErrorStringA");
  fRasDial = (pRasDial)
    GetProcAddress(hRasInstance, "RasDialA");
  fRasEnumConnections = (pRasEnumConnections)
    GetProcAddress(hRasInstance, "RasEnumConnectionsA");
  fRasGetConnectStatus = (pRasGetConnectStatus)
    GetProcAddress(hRasInstance, "RasGetConnectStatusA");
  fRasEnumEntries = (pRasEnumEntries)
    GetProcAddress(hRasInstance, "RasEnumEntriesA");
   fRasGetEntryDialParams  = (pRasGetEntryDialParams)GetProcAddress(hRasInstance, "RasGetEntryDialParamsA");
  fRasHangUp = (pRasHangUp)
    GetProcAddress(hRasInstance, "RasHangUpA");
  if (!fRasGetErrorString || !fRasDial || !fRasEnumConnections ||
      !fRasGetConnectStatus || !fRasEnumEntries || !fRasHangUp) {
    LogEvents("Ошибка загрузки функций дозвона");
     Close();
     return;
  }
....

}
void TfmMainFtp::CheckRnaApp()
{
  if (Win32Platform == VER_PLATFORM_WIN32_NT)
    // фор Win9x
    return;
  HWND hWnd = FindWindow("RnaEngClass", 0);
  if (hWnd) {
    //Если в этот момент окно дозвона существует - прибиваем
    PostMessage(hWnd, WM_CLOSE, 0, 0);
    // И ждем на всякий случай.
    Sleep(5000);
  }
}

//---------------------------------------------------------------------------

void __fastcall TfmMainFtp::acConnectWithInetExecute(TObject *Sender)
{
ttTimer->Enabled = false;
 hRas = CheckForConnections();
 String PBEntry;
  if (hRas) {
   LogEvents("Используем существующее соединение...");
    ttTimerClick->Enabled = true;
    AlreadyConnected = true;
    // Не надо вызывать  - соедиенение с Инетом уже есть
    return;
  }
  else {
    // Получаем соединение по умолчанию
  PBEntry = GetPhoneBookEntry();
    if (PBEntry == "") {
      LogEvents("Нет соединений");
      Close();
    }
  }

  LogEvents("Соединение отсутствует. Дозваниваемся...");
   CheckRnaApp();
  // Устанавливаем соединение
  RASDIALPARAMS params;
  params.dwSize = sizeof(params);
  strcpy(params.szEntryName, PBEntry.c_str());

   BOOL  PwdDetected = FALSE;
   DWORD Result = fRasGetEntryDialParams(NULL,&params,&PwdDetected);

  DWORD res = fRasDial(0, 0, &params, 1, RasCallback, &hRas);
  if (res) {
    char buff[256];
    fRasGetErrorString(res, buff, sizeof(buff));
    LogEvents(buff);
    String MsgError = "При подключении произошла следующая ошибка:\n"+String(buff);
    if(Application->MessageBoxA(MsgError.c_str(),"Ошибка",MB_ICONQUESTION+MB_OKCANCEL)==IDOK){
    fRasHangUp(hRas);
     ttTimer->Enabled = true;
     return;
    }
    else Close();
  }

}

HRASCONN TfmMainFtp::CheckForConnections()
{
if(GetInternetConnection())return (void*)(1);
  char buff[256];
  RASCONN rc;
  rc.dwSize = sizeof(RASCONN);
  DWORD numConns;
  DWORD size = rc.dwSize;
  // Enumerate the connections.
  DWORD res = fRasEnumConnections(&rc, &size, &numConns);
  if (!res && numConns == 0)
    // No connections, return 0.
    return 0;
  if (res) {
    // Error. Report it.
    fRasGetErrorString(res, buff, sizeof(buff));
    LogEvents(buff);
    String MsgError = "При подключении произошла следующая ошибка:\n"+String(buff);
    if(Application->MessageBoxA(MsgError.c_str(),"Ошибка",MB_ICONQUESTION+MB_OKCANCEL)==IDOK){
    fRasHangUp(rc.hrasconn);
     ttTimer->Enabled = true;
     return 0;
    }
    else Close();
    return 0;
  } else {
    // Получсаем статус
    RASCONNSTATUS status;
    status.dwSize = sizeof(status);
    res = fRasGetConnectStatus(rc.hrasconn, &status);
    if (res) {
      // Error. Report it.
      fRasGetErrorString(res, buff, sizeof(buff));
      LogEvents(buff);
      String MsgError = "При подключении произошла следующая ошибка:\n"+String(buff);
    if(Application->MessageBoxA(MsgError.c_str(),"Ошибка",MB_ICONQUESTION+MB_OKCANCEL)==IDOK){
    fRasHangUp(rc.hrasconn);
     ttTimer->Enabled = true;
     return 0;
    }
    else Close();
      return 0;
    } else {
      // Ищем соединение и опрашиваем ее
      if (status.rasconnstate == RASCS_Connected) {
        LogEvents("Установлено соединение:");
        LogEvents("Тип устройства:\t" +
          String(rc.szDeviceType));
        LogEvents("Название устройства: " +
          String(rc.szDeviceName));
        LogEvents("Соединение: " +
          String(rc.szEntryName));
        return rc.hrasconn;
      } else {
        //Если соединение запущено но имеет статус дисконнект
        LogEvents("Connection Error");
        String MsgError = "При подключении произошла следующая ошибка:\n"+String(buff);
         if(Application->MessageBoxA(MsgError.c_str(),"Ошибка",MB_ICONQUESTION+MB_OKCANCEL)==IDOK){
         fRasHangUp(rc.hrasconn);
         ttTimer->Enabled = true;
         return 0;
        }
        else Close();
        return 0;
      }
    }
  }
  return 0;
}
String TfmMainFtp::GetPhoneBookEntry()
{

 LogEvents("Инициализация соединения");
 String S;
 Reg = new TRegistry;
 Reg->RootKey = HKEY_LOCAL_MACHINE;
 Reg->OpenKeyReadOnly("\\SOFTWARE\\Microsoft\\RAS AutoDial\\Default");

 if(Reg->ValueExists("DefaultInternet")){
  S = Reg->ReadString("DefaultInternet");
  return S;
  }
 else{
  RASENTRYNAME* entries = new RASENTRYNAME;
  entries->dwSize = sizeof(RASENTRYNAME);
  DWORD numEntries;
  DWORD size = entries->dwSize;
  DWORD res = fRasEnumEntries(0, 0, entries, &size, &numEntries);
  if (numEntries == 1) {
    String entryName = entries->szEntryName;
    delete[] entries;
    return entryName;
  }

  if (res == ERROR_BUFFER_TOO_SMALL) {
     delete[] entries;
    entries = new RASENTRYNAME[numEntries];
    entries[0].dwSize = sizeof(RASENTRYNAME);
    res = fRasEnumEntries(0, 0, entries, &size, &numEntries);
    if (res) {
      char buff[256];
      fRasGetErrorString(res, buff, sizeof(buff));
      LogEvents(buff);
    }
  }
  delete[] entries;
  delete Reg;
  return S;
 }
}
[/CODE]
9.5K
25 декабря 2006 года
Borgir
97 / / 20.12.2006
ОК, спасибо. Буду пробовать.
Я тут нашел еще один способ. У СОМ-порта есть такая функция WaitCommEvent, она то у меня и будет ждать прихода данных из СОМ-порта.

Всем спасибо за участие.
Тему можно закрывать
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог