Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Работа с базами данных 2 страница




Свойство TableName позволяет выбрать фактическое имя таблицы из выпадающего списка.

Свойство Exclusive разрешает или запрещает другому приложению обращаться к таблице, пока вы ее используете сами.

Свойство IndexFiles открывает диалог выбора индексного файла для таблицы.

Свойство IndexName задает правило сортировки данных, отличное от упорядочивания по первичному ключу (primary key order).

Свойство Filter позволяет устанавливать критерий фильтрации, в соответствии с которым адресуется некоторое подмножество записей таблицы.

Свойства MasterFields и MasterSource участвуют в образовании связи двух таблиц (ведущей и ведомой) по принципу master-detail.

С компонентом TTable связаны следующие методы:

GotoCurrent() – синхронизирует перемещения курсора по нескольким табличным компонентам, ассоциированным с одной и той же фактической таблицей.

First(), Next(), Prior(), Last() и MoveBy() – используются для навигации по данным таблицы.

SetKey(), FindKey(), FindNearest(), GotoKey() и GotoNearest() – используются для поиска по специфическим значениям ключей.

Append(), Insert(), AppendRecord() и InsertRecord() добавляют новую запись к таблице.

Delete() – вычеркивает текущую запись.

Edit() – разрешает приложению модифицировать записи, a Post() вызывает фактическое изменение содержимого базы данных.

Запросы. Компонент TQuery обеспечивает доступ к нескольким таблицам одновременно. Вид возвращаемого набора данных зависит от SQL запроса, который может быть либо статическим, когда параметры запроса задаются на стадии проектирования, или динамическим, когда параметры определяются во время выполнения программы.

Свойство Active разрешает или запрещает режим просмотра "живых данных", возвращаемых запросом на этапе проектирования. Свойство DatabaseName содержит псевдоним базы данных или полный путь к ее каталогу, необходимые для разрешения запроса. Свойство SQL используется для ввода команды SQL посредством строчного редактора списка, который открывается двойным щелчком мышью.

Аналогично таблице, компонент запроса TQuery также инкапсулирует следующие методы:

First(), Next(), Prior(), Last() и MoveBy() – используются для навигации по результатам динамического запроса;

Append(), Insert(), AppendRecord() и InsertRecord() – добавляют новую запись к таблице;

Delete() – удаляет текущую запись;

Edit() – разрешает приложению модифицировать записи;

Post() – вызывает фактическое изменение содержимого базы данных.

Следующая процедура иллюстрирует процесс создания простой формы для базы данных StudentBase:

1.Поместите на форму Form1 пять наборов TTable, TDataSource, TDBGrid, TDBNavigator.

2. Установите свойства объектов таблиц Table1 – Table5

DatabaseName =StudentBase; Table1Name =students,

Table2Name=predmets, Table3Name =prepods, Table4Name=exams,

TableName5=raspisanie.

3. Установите свойства объектов источников DataSourcel ->

DataSet =Table1, …, DataSource5 -> DataSet =Table5

4. Установите свойства компонентов отображения данных

DBGrid1 -> DataSource = DataSource1, …, DBGrid5 ->DataSource = DataSource5

5. Установите свойство Active = true для таблиц, чтобы сразу же отобразить данные в сетках на форме.

6.Создайте новую форму Form2 и поместите на нее компоненты Query1, Table1, DataSourse1, DBGrid1. Задайте свойства этих компонентов.

7. В свойстве SQL компонента Query1 задайте SQL запрос:

 

SELECT StudentsName, ExamMark, PrepodName, PredmetName

FROM students, exams, predmets,prepods,raspisanie

WHERE students.Id_stud=exams.Id_stud

AND raspisanie.Id_predmet=exams.Id_predmet

AND raspisanie.Id_prepod=prepods.Id_prepod

AND exams.Id_predmet=predmets.Id_predmet

AND predmets.PredmetName LIKE 'Програм'

AND exams.ExamMark >'5';

8. Выполните компиляцию и запустите приложение. На рис. 19 показан результат выполнения приложения.

 

 

Рис. 19. Результат выполнения приложения

 

Чтобы связать ведущую таблицу students с ведомой таблицей exams необходимо выполнить следующее:

1. Активизируйте ведомую таблицу Table5 и установите свойство MasterSource = DataSource1

2. Дважды щелкните мышью в графе значений свойства MasterFields и в открывшемся окне редактора связи полей выберите Id_stud (связующее поле таблиц) из выпадающего списка Available Indexes; задайте Id_stud в списках Detail Fields и Master Fields; нажмите кнопку Add, чтобы добавить в список Joined Fields соединение Id_Stud-> Id_Stud; нажмите кнопку OK, подтверждая сделанный выбор.

Следующая процедура иллюстрирует процесс создания формы со статическим запросом к таблице EMPLOYEE для получения всей информации о служащих, зарплата которых превышает заданную величину:

1. Поместите компонент TQuery на форму.

2. Установите псевдоним адресуемой базы данных сервера в свойстве DatabaseName. В примере используется псевдоним BCDEMOS локальной демонстрационный базы данных, содержащей, в частности, таблицу служащих некоторого предприятия.

3. Откройте строчный редактор списка, введите команду SQL

SELECT * FROM EMPLOYEE WHERE Salary>40000 и нажмите кнопку ОК.

4. Поместите на форму компонент TDataSource и установите его свойство DataSet = Query1.

5. Поместите на форму компонент управления TDBGrid и установите его свойство DataSource = DataSource1.

6. Установите свойство Active = true для запроса Queryl с тем, чтобы сразу же отобразить живые данные в компоненте управления.

Далее приводится пример приложения для выполнения динамических SQL-запросов к таблице служащих.

Свойство SQL компонента TQuery имеет тип TStrings и содержит список текстовых строк наподобие массива. Листинг показывает обработчик события Button1Click, реализующий ввод запроса пользователем при нажатии кнопки на форме. Введенная команда SQL записывается в строчный массив (того же типа TStrings) свойства Memo1->Lines компонента TMemo. Результаты запроса можно, как и в предыдущем примере, отобразить с помощью компонента TDBGrid.

 

void__fastcall TForm1::Button1Click(TObject *Sender) {

// Проверить, введена ли какая-то строка в Memo1

if (strcmp(Memo1->Lines->Strings[0].c_str(), "") = = 0) (

MessageBox(0, "Не введен SQL-запрос", "Ошибка", MB_OK);

return;

}

else {

// Исключить предыдущий запрос, если он имел место

Queryl->Close ();

// Очистить свойство SQL от предыдущего запроса

Queryl->SQL->Clear ();

// Присвоить введенный в Memo1 текст свойству SQL

Queryl->SQL->Add(Memo1->Lines->Strings[0].c_str());

try{

Query1->Open(); // выполнить команду SQL

}

catch(EDBEngineError* dbError){}.// обработка ошибок BDE

{

for (int i=0; i<dbError->ErrorCount; i++)

MessageBox (0, dbError[i].Message.c_str(), "SQL Error", MB_OK);

}

}

}

 

Для динамического формирования текста командной строки SQL во время выполнения программы удобно использовать стандартную функцию языка С sprintf(). Эта функция замещает параметры форматирования (%s, %d, %n и т.д.) передаваемыми значениями. Например, в результате подстановки значений параметров форматирования

 

tblName = "Student";

fldName = "Kurs";

fldValue =2;

char sqls[80];

sprintf(sqls, "SELECT * FROM %s WHERE %s = %d", tblName, fldName, fldValue);

символьный массив sqls будет содержать следующую команду:

SELECT * FROM Student WHERE Kurs =2.

Далее созданный запрос выполняется

Query1->Close();

Query1->SQL->Clear();

Query1->SOL->Add(sqls);

try{

Query1 -> Open(); // выполнить команду SELECT

}

catch(EDBEngineError* dbError) // обработка ошибок BDE

{ }

}

 

Метод Open() предназначен для передачи серверу команды Select языка SQL для исполнения. Существуют другие команды SQL, например, команда UPDATE, которая обновляет содержимое некоторой записи, но не возвращает какой бы то ни было результат. Для исполнения сервером таких запросов следует использовать метод ExecSQL() вместо метода Open().

5.8. Соединения с базой данных и транзакции

Компонент TDatabase позволяет создавать локальный псевдоним базы данных, не требуя его наличия в конфигурационном файле BDE. Свойство AliasName содержит псевдоним существующей базы данных, определенный утилитой конфигурации BDE. Указание этого свойства является альтернативой значения свойства DriverName.

Свойство DatabaseName позволяет создать локальный псевдоним базы данных в дополнение к значениям AliasName или DriverName.

Свойство DriverName содержит имя драйвера BDE при создании локального псевдонима по значению DatabaseName. Указание этого свойства является альтернативой значения свойства AliasName.

Свойство Params содержит строчный массив параметров одиночного соединения (полный путь, имя сервера и т.д.).

Компонента TDatabase может использоваться для управления транзакциями. Примером транзакции является перевод денежных средств с банковских счетов. Такая транзакция состоит в добавлении суммы к новому счету и вычитании этой суммы из исходящего счета. Если выполнение любой из операций терпит неудачу, вся операция считается незавершенной. SQL-серверы дают возможность "прокручивать назад" команды при возникновении ошибки, не производя изменений в базе данных. Как правило, транзакция содержит несколько команд, поэтому начало транзакции надо отметить методом StartTransaction(). Как только транзакция началась, все ее исполняемые команды находятся во временном состоянии до тех пор, пока один из методов Commit() или Rollback() не отметит конец транзакции. Вызов Commit() фактически модифицирует данные, а вызов Rollback() отменяет всякие изменения.

Ниже приводится листинг, который реализует транзакцию по изменению адреса фирмы на примере связанных таблиц CUSTOMER и ORDERS. Старый адрес, введенный пользователем в область редактирования EditOld, заменяется на новый, введенный в область редактирования EditNew. В этом примере компонентный объект Database1 использовался для одиночного соединения с базой данных, поддерживающего выполнение одиночной транзакции. Этот объект необходимо каким-то образом связать с псевдонимом базы данных: или установкой соответствующих свойств компонента, или определив параметры соединения (такие как тип драйвера, имя сервера, имя пользователя, пароль) во время выполнения программы. Воспользуемя первым способом соединения на стадии проектирования формы приложения, установив нужные значения свойств компонента.

 

void__fastcall TForm1::Button1Click(TObject *Sender) {

char sqls[250]; // массив для хранения команды SQL

try{

Database1->StartTransaction ();

Query1->SQL->Clear ();

// Изменить EditOld на EditNew в таблице CUSTOMER

sprintf(sqls, "UPDATE CUSTOMER SET Addrl = \"%s\" WHERE

(Addrl = \"%s\")", EditNew->Text.c_str(), EditOld->Text.c_str());

Query1->SQL->Add(sqls);

Query1->ExecSQL ();

Query1->SQL->Clear ();

// Изменить EditOld на EditNew в таблице ORDERS

sprintf(sqls, "UPDATE ORDERS SET ShipToAddrl = \"%s\" WHERE

(ShipToAddrl = \"%s\")", EditNew->Text.c_str(),

EditOld->Text.c_str());

Query1->SQL->Add(sqls);

Query1->ExecSQL();

// Внести все изменения, сделанные до этого момента

Database1->Commit();

Table1->Refresh();

Table2->Refresh();

}

catch(EDBEngineError* dbError) // обработка ошибок BDE

{

for (int i=0; i<dbError->ErrorCount; i++)

MessageBox (0, dbError[i].Message.c_str(), "SQL Error", MB_OK);

Database1->Rollback();

return;

} catch (Exception* exception) // обработка других исключений

{}

}

5.9. Управление данными

Остановимся на особенностях использования компонента навигатора TDBNavigator. Нажимая на кнопки компонента First, Prior, Next и Last, можно перемещаться от записи к записи, а с помощью кнопок Insert, Delete, Edit, Post, Cancel и Refresh – производить редактирование.

Свойство DataSource соединяет кнопки управления панели навигатора с компонентами доступа к наборам данных через компонент источника. Изменяя значение этого свойства во время выполнения программы, можно использовать один и тот же компонент для навигации по разным таблицам. Например, можно разместить на форме два компонента редактируемого ввода DBEdit1 и DBEdit2, связанные с таблицами CustomersTable и OrdersTable через источники данных CustomersSource и OrdersSource, соответственно. Когда пользователь выбирает название фирмы (поле Company в DBEdit1), навигатор тоже должен соединяться с источником CustomersSource, а когда активизируется номер заказа (поле OrderNo в DBEdit2), навигатор должен переключаться на источник OrdersSource. Чтобы реализовать подобную схему работы навигатора, необходимо написать обработчик события OnEnter для одного из объектов компонента редактирования, а затем присвоить этот обработчик другому объекту.

Свойство VisibleButtons позволяет убрать ненужные кнопки, например, кнопки редактирования на форме, предназначенной для просмотра данных. Во время выполнения программы можно динамически прятать или вновь показывать кнопки навигатора – в ответ на определенные действия пользователя или на изменения состояния приложения. Предположим, вы предусмотрели единый навигатор для редактирования таблицы CustomersTable и для просмотра таблицы OrdersTable. Когда навигатор подключается ко второй таблице, желательно спрятать кнопки редактирования Insert, Delete, Edit, Post, Cancel и Refresh, а при подключении к первой таблице – снова показать их.

СвойствоShowHint разрешает или запрещает высвечивать подсказку с названием кнопки навигатора, когда на нее наведен курсор. Значение false (устанавливается по умолчанию) запрещает подсказки для всех кнопок.

Свойство Hints содержит массив текстовых подсказок для каждой кнопки навигатора

Итак, проектирование формы приложения СУБД в среде C++Builder в простейшем случае требует выполнения следующих действий:

1. Перенесите на форму компонент TTable или TQuery со страницы Data Access и установите его свойства.

2. Перенесите на форму компонент DataSource и в свойстве DataSet укажите ссылку на объект набора данных (например, Table1 или Query1).

3. Перенесите на форму нужные компоненты отображения и редактирования данных со страницы DataControls и в их свойстве DataSource задайте источник данных (например, DataSource1). Определите отображаемое поле набора данных в свойстве DataField.

4. Если на предыдущем шаге вы выбрали компонент TDBGrid, то используйте его совместно с компонентом навигатора TDBNavigator.

Вопросы

1. Что представляет собой псевдоним БД и как он создается?

2. Как создать таблицу с помощью программы Database Desktop?

Какие другие средства для создания таблиц можно использовать?

3. Какие компоненты используются для связи таблиц БД с компонентами визуализации и управления данными DBGrid, DBEdit?

4. Как связать компоненты Table и Query с нужной таблицей БД?

5. Как связать компонент DBNavigator с нужной таблицей БД?

6. Что такое первичные и вторичные индексы для таблицы и как их создать?

7. Что такое SQL и из каких частей он состоит?

8. Что означают следующие SQL-запросы:

a) SELECT name, projectname FROM emploee, project

WHERE empno=team_leader;

б) SELECT name, salary FROM emploee, prohibit

WHERE salary>2900;

9. Как использовать SQL-запрос в C++Builder?

Упражнения

В следующих упражнениях создать указанные таблицы и записать SQL запрос для выборки данных из обеих таблиц.

1. Построить головную таблицу «Телефонный справочник» с полями: Номер телефона, Адрес, а также вспомогательную таблицу «Население города» с полями: Номер телефона Фамилия И.О., Год рождения, Пол, Адрес.

2. Головная таблица содержит данные о подразделениях предприятия: Отдел – номер, название(например, Цех1, Бухгалтерия), тип отдела (например, Управление, Производство и т. д.). Вспомогательная таблица содержит сведения о сотрудниках: ID, Фамилия И.О., Год рождения, Пол, Номер_Отдела. Связать таблицы по полю Номер_Отдела.

3. БД содержит следующие связанные таблицы: «Сведения о покупателях»:ID, Фамилия И.О., адрес, Номер банковского счёта, номер заказа и «Сведения о заказах»: Наименование товара, ID, Количество, Стоимость, Дата заказа.

4. БД содержит следующие связанные таблицы: «Студенты»: Номер зачётной книжки, Фамилия, Имя, Отчество, Специализация, Курс, Группа; «Учебный план»: Специализация, Курс, Предмет1, Предмет2,…; «Журнал успеваемости»: Фамилия, Имя, Отчество, Предмет 1, Предмет 2, …

5. БД «Абитуриенты» содержит следующие связанные таблицы:
«Сведения об абитуриентах»: Номер личной карточки, Фамилия, Имя, Отчество, Факультет, Специальность,; «Сведения о сдаваемых предметах»: Специальность, Предмет; «Сведения об оценках»: Фамилия, Имя, Отчество, Номер личной карточки, Предмет, Оценка.

6. БД «Автомобили» содержит следующие таблицы:
«Общие сведения об автомобиле»:ID, Марка, Тип, Производитель; «Характеристика автомобиля»: Марка, Мощность двигателя, Тип двигателя, Стоимость.

7. БД «Лабораторные занятия» содержит следующие таблицы:
«Преподаватели»: ID, Фамилия, Имя, Отчество, Предмет, Курс, Группа; «Студенты»:ID, Фамилия, Имя, Отчество, Курс, Группа;
«Пропуски занятий»: Фамилия, Имя, Отчество, Курс, Группа, Предмет, Пропущено.

8. БД «Конференция» содержит следующие таблицы:
«Расписание заседаний»:Номер, Название секции, Дата, Время;
«Сведения об участниках»: Фамилия И.О., Название секции, Название доклада; «Оргработа»: Фамилия, Имя, Отчество, Дата приезда, Дата отъезда, Потребность в гостинице, Оргвзнос.

9. БД «Библиотека» содержит следующие таблицы:
«Общая характеристика единицы хранения»: Инвентарный номер, Тип издания (журнал, книга, рукопись), Название; «Характеристика издания»: Тип издания, Авторы, Название, Издательство, Год издания, Номер, Количество страниц.

10. БД «Магазин» содержит следующие таблицы: «Товары»: Артикул, Наименование товара, Количество, Дата поставки, Цена; «Поставщики»: Название организации, Наименование товара, Количество, Дата поставки, Адрес организации;
«Покупатели»: Название организации, Наименование товара, Количество, Дата покупки, Адрес покупателя.

11. БД «Поликлиника» содержит следующие таблицы:
«Врачи»: Участок, Фамилия И.О., Специальность;
«Пациенты»:ID, Фамилия И. О., Диагноз, Возраст, Участок.

12. БД «Спортивная база» содержит следующие таблицы:
«Тренеры»:ID, Фамилия, Имя, Отчество, Вид спорта, Секция;
«Спортсмены»: ID, Фамилия, Имя, Отчество, Вид спорта, Секция, Рейтинг, Возраст.

6. СЕТЕВЫЕ ПРОГРАММЫ И СОКЕТЫ

Понятие «сокет» (socket) означает "гнездо", "разъем" по аналогии с гнездами на аппаратуре. В соответствии с этой аналогией, можно связать два "гнезда" соединением и передавать между ними данные. Каждое гнездо принадлежит определённому хосту (host – хозяин, держатель). Каждый хост имеет уникальный IP (Internet Packet) адрес, представляющий группу из четырех чисел, разделенных точками.

Переданная по IP адресу на хост информация поступает на один из портов хоста. Порт определяется числом от 0 до 65535. После того, как сокет установлен, он имеет вполне определённый адрес, записывающийся так [host]:[port]. Например, 127.0.0.1:8888 означает, что сокет занимает порт 8888 на хосте 127.0.0.1(на данном компьютере). Чтобы не использовать труднозапоминаемый IP адрес, для доступа к хостам используется система имен DNS (DNS – Domain Name Service), поддерживаемая специальным сервером. Цель этой системы – сопоставлять IP адресам символьные имена. Например, адресу "127.0.0.1" в большинстве компьютеров соответствует имя "localhost", что означает сам компьютер, на котором выполняется программа.

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

Для организации сетевых соединений (сокетов) в C++ Builder используются классы TСlientSocket и TServerSocket из группы компонентов Internet. Ниже описывается работа с компонентом TСlientSocket по установке соединения.

Определение свойств Host и Port. Поместим компонентTClientSocket на форму. Чтобы установить соединение, нужно присвоить свойствам Host и Port компонента TClientSocket значения, соответствующие адресу сервера. Host – это символьное имя компьютера-сервера, с которым надо соединиться (например: localhost, nitro.borland.com или mmf410-2), либо его IP-адрес (например: 127.0.0.1, 192.168.0.88). Port – номер порта (от 1 до 65535) на данном хосте для установления соединения. Обычно номера портов выбираются, начиная с 1001 (номера меньше 1000 могут быть заняты системными службами, например, по умолчанию POP – 110, Http – 80).

Открытие сокета. После назначения свойствам Host и Port соответствующих значений, можно приступить к открытию сокета. Для этого нужно присвоить свойству Active значения true. Здесь полезно вставить обработчик исключительной ситуации на случай, если соединиться не удается. Открытие сокета можно выполнить, также с помощью метода ClientSocket->Open();

Авторизация. На этом этапе вы посылаете серверу свой логин (имя пользователя) и пароль. Этот пункт можно пропустить, если сервер не требует ввода логинов или паролей.

Посылка/прием данных – это, собственно и есть то, для чего открывалось сокетное соединение;

Закрытие сокета – после выполнения операций необходимо закрыть сокет, присвоив свойству Active значение false или вызовом метода ClientSocket->Close();.

Свойства и методы компонента TClientSocket. На рис. 20 и 21 показаны свойства и события компонента TClientSocket в инспекторе объектов. В табл. 18 приведены их краткие описания.

 

 
 

Рис. 20. Свойства компонента TClientSocket

 
 

 

Рис. 21. События компонента TclientSocket

Пример программы-клиента на основе сокета. Поместим на форму компонент TClientSocket, две кнопки Button1 и Button2, два окна типа TEdit и два компонента Memo1 и Memo2. При нажатии на кнопку GetFromServeSendToClient вызывается обработчик события OnClick – Button1Click(). Перед этим в Edit1 нужно ввести хост-имя, а в Edit2 – порт удаленного компьютера. Когда TClientSocket должен прочитать информацию из сокетного соединения, возникает событие OnRead и вызывается функция ClientSocketRead().

 

Таблица 18

Свойства События
Active – True – сокет открыт, а False –закрыт. Host – строка (типа String), указывающая на имя компьютера, к которому следует подключиться. Address – строка (типа String), указывающая на IP-адрес компьютера, к которому следует подключиться. Если вы укажете в Host символьное имя компьютера, то IP адрес будет запрошен у DNS. Port – номер порта (от 1 до 65535), к которому следует подключиться. Service – строка, определяющая службу (ftp, http, pop и т.д.), к порту которой произойдет подключение. ClientType – тип соединения ctNonBlocking или ctBlocking OnConnect – возникает при установлении соединения. В обработчике события можно начинать авторизацию или прием/передачу данных. OnConnecting – возникает при установлении соединения, но соединение еще не установлено. Обычно такие промежуточные события используются для обновления статуса. OnDisconnect – возникает при закрытии сокета из вашей программы либо из-за сбоя. OnError – возникает при ошибке в работе сокета. Операторы открытия сокета следует заключить в блок try..catch. OnLookup – возникает при попытке получения от DNS IP-адреса хоста. OnRead – возникает, когда удален-ный компьютер послал данные. OnWrite – возникает, когда вам разрешена запись данных в сокет.

 
 

На рис. 22 показана форма приложения в процессе проектирования.

 

 

Рис. 22. Форма приложения-клиента

 

Ниже приводятся коды приложения-клиента.

 

TForm1 *Form1;

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

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//открытие клиента и установка соединения

void __fastcall TForm1::Button1Click(TObject *Sender)

{

TClientSocket *cs = Form1->ClientSocket; // формируем указатель cs->Close(); // закрытие соединения(если слушали порт ранее)

try

{

cs->Port=Form1->PortEdit->Text.ToInt();//получение номера порта

cs->Host = HostEdit->Text; // получения адреса хоста

cs->Active = true; // установка соединения

}

catch(...)

{

Memo1->Text = "Some problem with connection";// если введены

//неверные значения

}

}

//очистка окна

void __fastcall TForm1::ClearClick(TObject *Sender)

{

Memo1->Clear();

}

// считывание клиентом сообщения

void __fastcall TForm1::ClientSocketRead(TObject *Sender, TCustomWinSocket *Socket)

{

Memo1->Text = Socket->ReceiveText(); // запись сообщения в поле клиента

}

void __fastcall TForm1::ClientSocketWrite(TObject *Sender,

TCustomWinSocket *Socket)

{

Socket->SendText(Memo2->Text); //

}

//вызов события посылки сообщения

void __fastcall TForm1::Button2Click(TObject *Sender)

{

Form1->ClientSocketWrite(Form1,Form1->ClientSocket->Socket);

}

 

Ниже описываются методы свойства Socket компонента TClientSocket. Свойство Socket в свою очередь является объектом класса TСustomWinSocket.

SendText(String) – посылка текстовой строки через сокет.

SendStream() – посылка содержимого указанного потока через сокет. Пересылаемый поток должен быть открыт.

SendBuf(Buf, Count) – посылка буфера через сокет. Буфером может являться любой тип, например, структура или простой тип int. Буфер указывается параметром Buf, вторым параметром необходимо указать размер пересылаемых данных в байтах (Count).

ReceiveText() – получить сообщение.

Программирование серверов на основе сокетов. Следует заметить, что для сосуществования отдельных приложений клиента и сервера не обязательно иметь несколько компьютеров. Достаточно иметь лишь один, на котором можно одновременно запустить и сервер, и клиент. При этом в качестве имени компьютера, к которому надо подключиться, нужно использовать хост-имя localhost или IP-адрес – 127.0.0.1.

Сервер, основанный на сокетном протоколе, позволяет обслуживать сразу множество клиентов. Причем, ограничение на их количество вы можете указать сами (или убрать это ограничение, как сделано по умолчанию). Для каждого подключенного клиента сервер открывает отдельный сокет, по которому можно обмениваться данными с клиентом. Другим решением является создание для каждого подключения отдельного процесса (Thread).

Создание сервера включает следующие шаги:

Определение свойств Port и ServerType – чтобы к серверу могли подключаться клиенты, порт, используемый сервером, должен совпадать с портом, используемым клиентом. Свойство ServerType определяет тип подключения.

Открытие сокета – открытие сокета и указанного порта. Осуществляется установкой свойства ServerSocket->Active=true. Автоматически начинается ожидание подсоединения клиентов.

Подключение клиента и обмен данными с ним – клиент устанавливает соединение и начинается обмен данными с ним.

Отключение клиента – клиент отключается и закрывается его сокетное соединение с сервером.




Поделиться с друзьями:


Дата добавления: 2014-12-27; Просмотров: 519; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.153 сек.