И.А. Волкова, И.Г. Головин, Л.Н. Кузина, М.Г. Мальковский - Модельный SQL-интерпретатор (1114899), страница 3
Текст из файла (страница 3)
Пример-оболочка программы «Сервер»#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <stdio.h>#define ADDRESS “mysocket” // адрес для связиvoid main (){char c;inti, d, d1, len, ca_len;FILE * fp;struct sockaddr_un sa, ca;// получаем свой сокет-дескриптор:if((d = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) {perror (“client: socket”);exit (1);}// создаем адрес, c которым будут связываться клиентыsa.sun_family = AF_UNIX;strcpy (sa.sun_path, ADDRESS);// связываем адрес с сокетом;// уничтожаем файл с именем ADDRESS, если он существует,// для того, чтобы вызов bind завершился успешноunlink (ADDRESS);len = sizeof ( sa.sun_family) + strlen (sa.sun_path);if ( bind ( d, (struct sockaddr *)&sa, len) < 0 ) {perror (“server: bind”);exit (1);}// слушаем запросы на сокетif ( listen ( d, 5) < 0 ) {perror (“server: listen”);exit (1);7Волкова И.А., Головин И.Г., Кузина Л.Н., Мальковский М.Г.}// связываемся с клиентом через неименованный сокет с дескриптором d1:ca_len = sizeof ca;if (( d1 = accept ( d, (struct sockaddr *)&ca, &ca_len)) < 0 ) {perror (“server: accept”);exit (1);}/* ------------------------------------------ */// читаем запросы клиента, пишем клиенту:fp = fdopen (d1, “r”);c = fgetc (fp);/* ................................
*/send (d1, “server”, 7, 0);/* ................................ */putchar ( c );/* ................................ */close (d1);exit (0);}Приведенные выше примеры написаны в традиционном процедурном стиле. ЯзыкСи++ позволяет программировать как в таком стиле, так и в объектноориентированном стиле, используя мощное и выразительное понятие класса. Во второмслучае программы получаются существенно более компактными и понятными.Далее в качестве примеров приводятся оболочки программ для «Клиента» и «Сервера»,основанных на объектно-ориентированном интерфейсе для работы с сокетами (одна извозможных реализаций интерфейса приводится в приложении).2.4. Пример-оболочка программы «Клиент» вобъектно-ориентированном стиле#include <iostream>#include "sock_wrap.h"// см.
приложениеusing namespace std;using namespace ModelSQL;const char * address = "mysocket" // имя сокетаint main(int argc, char* argv[]){try {// создаём сокетUnClientSocket sock( address );// устанавливаем соединениеsock.Connect();// отправляем серверу строкуsock.PutString("Hello from client!");// печатаем на экран ответ от сервера8Модельный SQL-интерпретатор. Методическое пособие.cout << "Read from server: " << sock.GetString() << endl;// продолжаем диалог с сервером, пока в этом есть необходимость} catch (Exception & e) {// ошибка --- выводим текст сообщения на экранe.Report();}return 0;}2.5.
Пример-оболочка программы «Сервер» вобъектно-ориентированном стиле#include <iostream>#include "sock_wrap.h"// см. приложениеusing namespace std;using namespace ModelSQL;const char * address = "mysocket" // имя сокетаclass MyServerSocket : public UnServerSocket {public:MyServerSocket () : UnServerSocket (address) {}protected:void OnAccept (BaseSocket * pConn){// установлено соединение с клиентом, читаем сообщениеcout << "Read from client: " << pConn->GetString() << endl;// отправляем ответpConn->PutString("Hello from server.");// продолжаем диалог с клиентом, пока в этом есть необходимостьdelete pConn;}};int main(int argc, char* argv[]){try {// создаём серверный сокетMyServerSocket sock;// слушаем запросы на соединениеfor (;;)sock.Accept();} catch (Exception & e) {// ошибка --- выводим текст сообщения на экранe.Report();}return 0;}9Волкова И.А., Головин И.Г., Кузина Л.Н., Мальковский М.Г.3.
Средства межпроцессноговзаимодействия для сети ЭВМСетевые средства ОС UNIX также базируются на механизме сокетов, рассмотренномвыше, но работают в Internet-домене.В UNIX домене сетевой адрес процесса специфицируется стандартным описанием путик некоторому файлу. Этот домен не подходит для работы с сетью, так как не всекомпьютеры, связанные в сеть, работают в ОС UNIX, а следовательно, могут иметьразные способы спецификации адресов, поэтому при организации межпроцессноговзаимодействия для сети ЭВМ используется Internet-домен.Адресация в Internet-домене происходит следующим образом. Каждый компьютер всети имеет символическое сетевое имя (hostname) и уникальный 32-битный сетевойадрес (IP-адрес).
Для установления сетевого соединения с конкретным процессом,запущенном на некотором компьютере в сети, необходимо также указать 16-битныйномер порта, через который данный процесс готов установить сетевое соединение(пользовательским программам могут выдаваться порты с номерами от 1025 до 32767).Некоторые системные обслуживающие процессы имеют закреплённые стандартныеномера портов, такие процессы называют сетевыми сервисами.
Так, например, сервиспередачи файлов по протоколу FTP использует порт 21. Поэтому программа, желающаясвязаться с FTP-сервером на компьютере с сетевым адресом 12345, должна обратитьсяпо Internet-адресу (12345, 21).3.1. Преобразование сетевого имени в сетевойадресПользователю обычно известно сетевое имя своего компьютера. Если же это не так, томожно воспользоваться функцией gethostname.3.1.1.Функция gethostnameint gethostname (char * buffer, int buflen);Первый аргумент функции — символьный буфер, в который в результате выполненияфункции запишется строка — сетевое имя компьютера; второй аргумент — целоечисло — длина символьного буфера. В случае если длины буфера не хватает дляхранения сетевого имени, функция возвращает −1, иначе — 0.Чтобы использовать сетевое имя в качестве сетевого адреса, надо его преобразовать.Соответствия между сетевыми именами и сетевыми адресами хранятся в системномтекстовом файле /etc/hosts.3.1.2.Функция gethostbynamestruct hostent * gethostbyname (char * hostname);10Модельный SQL-интерпретатор.
Методическое пособие.У этой функции один аргумент (строка символов hostname) — сетевое имя. Онавозвращает указатель на структуру struct hostent, определенную во включаемом файле<netdb.h>:structcharсharintintcharhostent {* h_name;** h_aliases;h_addrtype;h_length;** h_addr_list//////////hostname ЭВМсписок синонимовтип адресов ЭВМдлина адресасписок адресов (для разных сетей)#define h_addr h_addr_list[0]};Если же указанного сетевого имени нет в базе данных, возвращается константа NULL.3.1.3.Получение номера портаДля всех стандартных сетевых сервисов существует перечень закреплённых за ниминомеров портов в текстовом файле /etc/services. Это облегчает программе-клиентупроизводить соединение со стандартным сетевым сервисом на любой другой машине.3.1.4.Функция getservbynameЭта функция используется для того, чтобы получить номер порта конкретнойобслуживающей программы.struct servent* getservbyname(char * name, char * proto);Первый аргумент функции — символическое имя стандартного сервиса («telnet», «ftp»,«smtp», «pop3» и т.п.), второй аргумент — символическое имя транспортногопротокола: «tcp» или «udp».
Второй аргумент нужен для того, чтобы определить, нужноли устанавливать сессию для гарантированной доставки пакетов с сохранениемочерёдности SOCK_STREAM («tcp») или достаточно передачи коротких сообщенийSOCK_DGRAM («udp»).Функция возвращает указатель на структуру типа struct servent, определенную вовключаемом файле <netdb.h>:structcharcharintchar};servent {* s_name;** s_aliases;s_port;* s_proto;////////имя обслуживающей программысписок синонимовномер портаиспользуемый протоколЕсли имя сервиса не найдено в базе данных, возвращается константа NULL.Обычные пользовательские программы могут использовать любые свободные порты,но их номера должны лежать в пределах от 1025 до 32767 в соответствии стребованиями ОС UNIX и ARPANET (international network administration),зарезервировавших номера меньшие 1025 для стандартных и системных сервисов.11Волкова И.А., Головин И.Г., Кузина Л.Н., Мальковский М.Г.3.2.
Порядок байтов в сетиИзвестно, что целые числа хранятся в различных компьютерах по-разному. Некоторыекомпьютеры хранят целые числа в перевернутом виде, т.е. старшие байты числа имеютменьший адрес по сравнению с младшим байтом, в других же наоборот старший байтимеет больший адрес.
Чтобы избежать путаницы при взаимодействии машин,использующих различный порядок байтов, network software требует, чтобы всецелочисленные данные были представлены в сетевом байтовом порядке. Для тогочтобы привести целые числа к сетевому байтовому порядку, используются следующиедве функции.3.2.1.Функция htonsshort htons (short i);3.2.2.Функция htonllong htonl (long i);Эти функции переводят короткие (htons) и длинные (htonl) целые числа из байтовогопорядка компьютера в сетевой.Следующие две функции производят обратные действия, т.е. переводят короткие идлинные целые числа соответственно из сетевого байтового порядка в представление,принятое на данном компьютере.3.2.3.Функция ntohsshort ntohs (short i);3.2.4.Функция ntohllong ntohl (long i);Замечание: функции gethostbyname и getservbyname возвращают все данные и ихструктуры в сетевом байтовом порядке, т.е.