Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Прикладное программирование на CC++ с нуля до мультимедийных и сетевых приложений
.pdf
Коммуникации по телефонным линиям 121
выставлены вами принудительно, вручную или заданы автоматически операционной системой. В любом случае в результате успешного подключения к
удаленному компьютеру в соответствующих полях можно будет увидеть используемые адреса на обоих концах соединения. О том, что подключение состоялось успешно (или, наоборот, возникли проблемы), можно увидеть в правом информационном поле.
После успешного подключения ваш и удаленный компьютеры составляют
сеть, подобную локальной, но использующую в качестве среды передачи данных телефонные линии. Теперь можно воспользоваться стандартным сетевым
сервисом Windows, но мы, как упоминалось выше, включили в программу
средства автономной транспортировки файлов. Чтобы проделать это, необходимо поставить отметку в поле Передать файл. Станет активной кнопка Âû-
брать файл, после чего откроется стандартное Windows-окно выбора объекта
для передачи. На приемном конце после получения файла также откроется
окно Windows для выбора места размещения полученных данных, и операция
транспортировки завершится. Кнопка ÎÒÊË производит отсоединение от
удаленной машины, а кнопка Выход завершает работу приложения.
Переходим к разработке программы. Как видно из представленного рисунка рабочего окна приложения, на форме проекта размещается довольно
много визуальных компонентов. Список Имя соединения является элементом
ComboBox, поле выбора Передать файл — компонент CheckBox, информационное поле справа — Memo. Остальные объекты представляют собой обычные
кнопки Button, метки Label и поля редактирования Edit. Кроме того, на форме
размещаются два диалоговых компонента OpenDialog è SaveDialog, предназначенные для выбора источника и приемника передачи файлов. Для осуществления самой передачи потребуются также уже знакомые нам компоненты потоковой транспортировки данных NMStrmServ è NMSttm.
Для использования функций системы удаленного доступа в проект необходимо включить заголовочный файл ras.h, который мы разместим в заголовке Unit1.h, текст которого представлен ниже.
#ifndef Unit1H
#define Unit1H
#include <ras.h>
#include <Classes.hpp>
#include <Controls.hpp>
#include <Dialogs.hpp>
#include <NMSTRM.hpp>
#include <Psock.hpp>
#include <StdCtrls.hpp>
//—————————————————————————————————————class TForm1 : public TForm
{
__published: // IDE-managed Components
TComboBox *ComboBox1;
TEdit *Edit1;
TEdit *Edit2;
TEdit *Edit3;

122 Глава 3. Передача информации в сетях
TEdit *Edit4;
TEdit *Edit5;
TMemo *Memo1;
TLabel *Label1;
TLabel *Label2;
TLabel *Label3;
TLabel *Label4;
TLabel *Label5;
TLabel *Label6;
TButton *Button2;
TButton *Button3;
TLabel *Label9;
TLabel *Label10;
TEdit *Edit6;
TEdit *Edit7;
TEdit *Edit8;
TLabel *Label11;
TButton *Button4;
TLabel *Label12;
TLabel *Label13;
TEdit *Edit9;
TEdit *Edit10;
TButton *Button5;
TButton *Button1;
TButton *Button6;
TButton *Button7;
TEdit *Edit11;
TButton *Button8;
TCheckBox *CheckBox4;
TNMStrmServ *NMStrmServ1;
TNMStrm *NMStrm1;
TOpenDialog *OpenDialog1;
TButton *Button9;
TSaveDialog *SaveDialog1;
void __fastcall ComboBox1Change(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button5Click(TObject *Sender);
void __fastcall Button6Click(TObject *Sender);
void __fastcall Button7Click(TObject *Sender);
void __fastcall CheckBox4Click(TObject *Sender);
void __fastcall Button8Click(TObject *Sender);
void __fastcall NMStrm1Connect(TObject *Sender);
void __fastcall NMStrm1ConnectionFailed(TObject *Sender);
void __fastcall NMStrm1Disconnect(TObject *Sender);
void __fastcall NMStrm1HostResolved(TComponent *Sender);
void __fastcall NMStrm1InvalidHost(bool &Handled);
void __fastcall NMStrm1MessageSent(TObject *Sender);

Коммуникации по телефонным линиям 123
void __fastcall NMStrmServ1ClientContact(TObject *Sender);
void __fastcall NMStrmServ1MSG(TComponent *Sender,
const AnsiString sFrom, TStream *strm);
void __fastcall Button9Click(TObject *Sender);
private: // User declarations
public: // User declarations
RASENTRY *rasentry;
RASCREDENTIALS *rascredentials;
RASENTRYNAME *arEntry;
RASDIALPARAMS *rasdialparams;
RASCONNSTATUS *rasconnstatus;
HRASCONN hrasconn;
unsigned long EntrySize,Count,Count1,BuffSize;
int i;
void RefreshConnList()
{
ComboBox1->Items->Clear();
arEntry =(RASENTRYNAME *)malloc(sizeof(RASENTRYNAME));
arEntry->dwSize=sizeof(RASENTRYNAME);
if((RasEnumEntries(NULL,NULL,arEntry,&BuffSize,&Count))!=0)
{
RasEnumEntries(NULL,NULL,arEntry,&BuffSize,&Count);
arEntry = (RASENTRYNAME *)malloc (BuffSize*Count);
arEntry->dwSize=sizeof(RASENTRYNAME);
};
if((RasEnumEntries(NULL, NULL,arEntry,&BuffSize,&Count))!=0)
Memo1->Lines->Add(">>RasEnumEntries UnSuccessfull");
else
{
Memo1->Lines->Add(">>RasEnumEntries Successfull");
if (Count==0)
Memo1->Lines->Add(">>No registered connections in Windows phonebook");
else
for (i=0;i<((int)Count);i++)ComboBox1->Items->Add(
arEntry[i].szEntryName);
};
};
__fastcall TForm1(TComponent* Owner);
};
//—————————————————————————————————————extern PACKAGE TForm1 *Form1;
//—————————————————————————————————————#endif
Здесь описан класс формы, куда мы дополнительно ввели различные
public-переменные. Описанием этих переменных мы заниматься не будем —
это, в первую очередь, некоторые структуры, необходимые для работы системы RAS. Формируется public-функция RefreshConnList(), представляющая для
нас первостепенный интерес. Функция предназначена для обновления списка

124 Глава 3. Передача информации в сетях
соединений, представленных в телефонной книге. Операции обновления необходимы при создании новых соединений, редактировании и удалении существующих. Функция используется в главном модуле неоднократно и поэтому сделана универсальной.
Снова не будем останавливаться на малосущественных операциях размещения структур в памяти, формирования информационных сообщений и
тому подобного. Здесь важно использование стандартной функции системы
RAS RasEnumEntries. Функция подготавливает для работы список соединений,
содержащихся в телефонной книге. С учетом требуемой универсальности
RasEnumEntries сначала вызывается в условном выражении и, если, например,
список пуст, вторично. Третий раз эта функция вызывается и генерирует
ошибку, если программе не удалось вообще «совладать» с телефонной книгой.
При успешном обнаружении списка соединений в книге выполняется цикл
заполнения компонента ComboBox соответствующими именами.
Дальнейшие действия разворачиваются в главном модуле Unit1.cpp, текст
которого представлен далее.
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma link "cdiroutl"
#pragma resource "*.dfm"
TForm1 *Form1;
//—————————————————————————————————————__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
RefreshConnList ();
}
//—————————————————————————————————————void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{
Memo1->Lines->Add(" ");
RasGetEntryProperties(NULL,ComboBox1->Text.c_str(),NULL,&EntrySize,NULL,NULL);
Memo1->Lines->Add(">>You've choosen");
Memo1->Lines->Add(ComboBox1->Text.c_str());
rasentry=(RASENTRY*)malloc(EntrySize);
rasentry->dwSize=EntrySize;
if(RasGetEntryProperties(NULL, ComboBox1->Text.c_str(),
rasentry, &EntrySize, NULL, NULL)!=0)
Memo1->Lines->Add("Ioeaea RasGetEntryProperties");
else
{
Memo1->Lines->Add(">>RasGetEntryProperties OK");
Edit1->Text=ComboBox1->Text.c_str();
Edit2->Text=rasentry->szLocalPhoneNumber;
Edit3->Text=rasentry->dwCountryCode;
Edit4->Text=rasentry->szDeviceName;

Коммуникации по телефонным линиям 125
Edit5->Text=rasentry->szDeviceType;
};
rascredentials = (RASCREDENTIALS*) malloc(sizeof(RASCREDENTIALS));
rascredentials->dwSize=sizeof(RASCREDENTIALS);
rascredentials->dwMask=RASCM_UserName+RASCM_Password+RASCM_Domain;
if(RasGetCredentials(NULL,lstrcpy(ComboBox1->Text.c_str(),
ComboBox1->Text.c_str()),rascredentials)!=0 )
Memo1->Lines->Add(">>RasGetCredentials failed");
else
{
Memo1->Lines->Add(">>RasGetCredentials OK");
Edit6->Text=rascredentials->szUserName;
Edit7->Text=rascredentials->szPassword;
Edit8->Text=rascredentials->szDomain;
};
}
//—————————————————————————————————————-
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char nam;
lstrcpy(&nam,ComboBox1->Text.c_str());
RasEditPhonebookEntry(Form1->Handle,NULL,&nam);
RefreshConnList();
}
//—————————————————————————————————————-
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Form1->Close();
}
//—————————————————————————————————————-
void __fastcall TForm1::Button3Click(TObject *Sender)
{
rasdialparams=(RASDIALPARAMS *) malloc(sizeof(RASDIALPARAMS));
rasdialparams->dwSize= sizeof(RASDIALPARAMS);
lstrcpy(rasdialparams->szEntryName,Edit1->Text.c_str());
lstrcpy(rasdialparams->szPhoneNumber,"");
lstrcpy(rasdialparams->szCallbackNumber,"");
lstrcpy(rasdialparams->szUserName,Edit6->Text.c_str());
lstrcpy(rasdialparams->szPassword,Edit7->Text.c_str());
lstrcpy(rasdialparams->szDomain,Edit8->Text.c_str());
RASDIALEXTENSIONS *extensions = (RASDIALEXTENSIONS *)
malloc(sizeof(RASDIALEXTENSIONS));
BYTE eapdata;
DWORD reqsize;
eapdata=(BYTE)malloc(reqsize);
if(RasGetEapUserData(NULL,NULL,Edit1->Text.c_str(),&eapdata,&reqsize)!=
ERROR_SUCCESS)
{
eapdata=(BYTE)malloc(reqsize);
if(RasGetEapUserData(NULL,NULL,Edit1->Text.c_str(),

126 Глава 3. Передача информации в сетях
&eapdata,&reqsize)!=ERROR_SUCCESS)
Memo1->Lines->Add( "unable to allocate memory for eapdata");
};
RASEAPINFO* eapinfo;
eapinfo=(RASEAPINFO* )malloc(sizeof(RASEAPINFO));
eapinfo->dwSizeofEapInfo=sizeof(eapdata);
eapinfo->pbEapInfo=(unsigned char*)eapinfo;
extensions->RasEapInfo=*eapinfo;
extensions->dwSize=sizeof(RASDIALEXTENSIONS);
extensions->dwfOptions=RDEOPT_UsePrefixSuffix;
extensions->hwndParent=Form1->Handle;
extensions->reserved=0;
extensions->reserved1=0;
hrasconn=0;
DWORD rh=0;
rh=RasDial(extensions,NULL,rasdialparams,NULL,NULL,&hrasconn );
if(rh!=0)
{
Memo1->Lines->Add("Can't esteblish connection");
Memo1->Lines->Add("RasDial Error =");
Memo1->Lines->Add(rh);
}
else
{
Memo1->Lines->Add("Esteblished connection");
CheckBox4->Enabled=true;
};
rasconnstatus=(RASCONNSTATUS *) malloc(sizeof(RASCONNSTATUS));
rasconnstatus->dwSize=sizeof(RASCONNSTATUS);
RasGetConnectStatus(hrasconn,rasconnstatus);
Memo1->Lines->Add(rasconnstatus->dwError);
RASPROJECTION rasprotocol;
RASPPPIP *ipinf;
ipinf=(RASPPPIP*) malloc(sizeof(RASPPPIP));
ipinf->dwSize=sizeof(RASPPPIP);
unsigned long bufsize1=sizeof(RASPPPIP);
rasprotocol=RASP_PppIp;
rh=RasGetProjectionInfo(hrasconn,rasprotocol,ipinf,&bufsize1);
if(rh!=0)
{
Memo1->Lines->Add("RasGetProjectionInfo failed");
Memo1->Lines->Add(rh);
Memo1->Lines->Add("RASPPPIP error is");
Memo1->Lines->Add(ipinf->dwError);
}
else
{
Memo1->Lines->Add("RasGetProjectionInfo OK");
Memo1->Lines->Add("Client's ip");
Memo1->Lines->Add(ipinf->szIpAddress);
Edit9->Text=ipinf->szIpAddress;
Memo1->Lines->Add("Server's ip");
Memo1->Lines->Add(ipinf->szServerIpAddress);

Коммуникации по телефонным линиям 127
Edit10->Text=ipinf->szServerIpAddress;
};
}
//—————————————————————————————————————-
void __fastcall TForm1::Button4Click(TObject *Sender)
{
RASCONN *rasconn;
rasconn=(RASCONN *)malloc(sizeof(RASCONN));
rasconn->dwSize=sizeof(RASCONN);
BuffSize=sizeof(RASCONN);
DWORD rec=RasEnumConnections(rasconn,&BuffSize,&Count1);
if(rec!=0)
{
Memo1->Lines->Add("RasEnumConnections failed");
Memo1->Lines->Add(rec);
}
else
{
for(i=0;i<((int)Count1);i++)
{
if(RasHangUp(rasconn->hrasconn)!=0)
{
Memo1->Lines->Add("RasHangUp failed");
Memo1->Lines->Add(RasHangUp(rasconn->hrasconn));
}
else
{
Memo1->Lines->Add("RasHangUp OK");
Memo1->Lines->Add(rasconn->szEntryName);
Memo1->Lines->Add("Disconnected");
};
};
};
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
Edit4->Clear();
Edit5->Clear();
Edit6->Clear();
Edit7->Clear();
Edit8->Clear();
Edit9->Text="127.0.0.1";
Edit10->Text="127.0.0.1";
}
//—————————————————————————————————————void __fastcall TForm1::FormCreate(TObject *Sender)
{
ComboBox1->Enabled=true;
Button3->Enabled=true;
Button4->Enabled=true;
Edit1->Enabled=true;

128 Глава 3. Передача информации в сетях
Edit2->Enabled=true;
Edit3->Enabled=true;
Edit4->Enabled=true;
Edit5->Enabled=true;
Edit6->Enabled=true;
Edit7->Enabled=true;
Edit8->Enabled=true;
Edit9->Enabled=false;
Edit10->Enabled=false;
}
//—————————————————————————————————————-
void __fastcall TForm1::Button5Click(TObject *Sender)
{
RasCreatePhonebookEntry(/*Form1->Handle*/NULL,NULL);
RefreshConnList();
}
//—————————————————————————————————————-
void __fastcall TForm1::Button6Click(TObject *Sender)
{
RefreshConnList();
}
//—————————————————————————————————————void __fastcall TForm1::Button7Click(TObject *Sender)
{
char *nam;
nam=(char *)malloc(1024);
lstrcpy(nam,ComboBox1->Text.c_str());
RasDeleteEntry(NULL,nam);
free(nam);
RefreshConnList();
}
//—————————————————————————————————————-
void __fastcall TForm1::CheckBox4Click(TObject *Sender)
{
if(CheckBox4->Checked==true)
{
Button9->Caption="Выбрать что отправлять";
Button9->Enabled=true;
Edit10->Enabled=true;
}
else
{
Edit11->Enabled=false;
Button8->Enabled=false;
Button9->Enabled=false;
Edit10->Enabled=false;
Label13->Caption="IP сервера (удаленного)";
};
}

Коммуникации по телефонным линиям 129
//—————————————————————————————————————-
void __fastcall TForm1::Button8Click(TObject *Sender)
{
TMemoryStream *MS;
NMStrm1->Host=Edit10->Text.c_str();
if(Edit11->Text=="")
Memo1->Lines->Add(">>Укажите файл, который надо отправить");
else
{
MS= new TMemoryStream();
try
{
MS->LoadFromFile(Edit11->Text);
Memo1->Lines->Add(NMStrm1->PostIt(MS));
}
catch(...){ }
MS->Free();
};
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrm1Connect(TObject *Sender)
{
Memo1->Lines->Add(">>Соединиться с "+NMStrm1->Host);
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrm1ConnectionFailed(TObject *Sender)
{
Memo1->Lines->Add(">>Соединиться с "+NMStrm1->Host+"не удалось");
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrm1Disconnect(TObject *Sender)
{
Memo1->Lines->Add(">>Соединение с "+NMStrm1->Host+" завершено");
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrm1HostResolved(TComponent *Sender)
{
Memo1->Lines->Add(">>Сервер "+NMStrm1->Host+" обнаружен");
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrm1InvalidHost(bool &Handled)
{
Memo1->Lines->Add(">>Неверный адрес. Укажите правильный и повторите
попытку");
}
//—————————————————————————————————————-

130 Глава 3. Передача информации в сетях
void __fastcall TForm1::NMStrm1MessageSent(TObject *Sender)
{
Memo1->Lines->Add(">>Поток ушел ;)");
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrmServ1ClientContact(TObject *Sender)
{
NMStrmServ1->ReportLevel=Status_Basic;
NMStrmServ1->TimeOut=90000;
Memo1->Lines->Add(">>У нас клиент ;)");
}
//—————————————————————————————————————-
void __fastcall TForm1::NMStrmServ1MSG(TComponent *Sender,
const AnsiString sFrom, TStream *strm)
{
TMemoryStream *SS;
SS=new TMemoryStream();
try
{
SS->CopyFrom(strm,strm->Size);
SaveDialog1->Execute();
Edit11->Text=SaveDialog1->FileName;
SS->SaveToFile(Edit11->Text.c_str());
Memo1->Lines->Add(">>Получен файл"+sFrom);
} catch(...){}
SS->Free();
}
//—————————————————————————————————————-
void __fastcall TForm1::Button9Click(TObject *Sender)
{
if(CheckBox4->Checked==true)
{
OpenDialog1->Execute();
Edit11->Text=OpenDialog1->FileName;
HANDLE fhandle=CreateFile(Edit11->Text.c_str(),GENERIC_READ,
FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(Edit11->Text=="")
Memo1->Lines->Add("Ничего не выбрали");
else
{
Memo1->Lines->Add("Выбрали файл <"+Edit11->Text+"> размером "+
(DWORD)GetFileSize(fhandle,NULL)+" áàéò");
Button8->Enabled=true;
};
}
}
Модуль выглядит довольно большим, но, в основном, текст содержит
понятные операции вывода информационных сообщений, активации кнопок
и тому подобное. Мы уже договорились, что такие элементы программы
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
