Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Прикладное программирование на CC++ с нуля до мультимедийных и сетевых приложений

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Коммуникации по телефонным линиям 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;
};
} }
Модуль выглядит довольно большим, но, в основном, текст содержит понятные операции вывода информационных сообщений, активации кнопок и тому подобное. Мы уже договорились, что такие элементы программы