Гнезда и интерфейс транспортного уровня



 

Гнезда представляют собой независимые от протокола услуги по организации сетевого интерфейса. Они способны обеспечить работоспособность методов межпроцессного взаимодействия в масштабах глобальной сети. Гнезда могут работать практически с любым протоколом (TCP — Transmission Control Protocol, UDP — User Datagram Protocol и др.). Обращаться к гнезду можно по IP-адресу хост-машины и номеру порта. Заданный таким образом адрес уникален в масштабах всей Internet, следовательно, два процесса, выполняемые на отдельных машинах, могут взаимодействовать друг с другом через гнезда.

Интерфейс транспортного уровня TLI (Transport Level Interface) стал ответом System V на появление гнезд в BSD UNIX. TLI был разработан на базе механизма STREAMS: он поддерживает большинство транспортных протоколов и более гибок, чем гнезда, хотя методика его использования и системные вызовы похожи на методику использования и системные вызовы гнезд. В стандарте X/Open TLI называется XTI. В стандарте POSIX гнезда и TLI не определены.

 

 

Гнезда

 

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

При использовании гнезд обычно применяются следующие стандартные домены: AF_UNIX (формат адреса — путевое имя UNIX) и AF_INET (формат адреса — хост-имя и номер порта).

Для каждого гнезда назначается тип, посредством которого определяется способ передачи данных между двумя гнездами. Если тип гнезда — виртуальный канал (virtual circuit), то данные передаются последовательно с достаточной степенью надежности. Если тип гнезда — дейтаграмма (datagram), то условие последовательности пересылки данных не выполняется и надежность их передачи низкая. Тип гнезда с установлением соединения — как правило, виртуальный канал, а тип гнезда без установления соединения — дейтаграмма.

Гнездо каждого типа поддерживает один или несколько транспортных протоколов, однако по умолчанию для виртуального канала используется TCP, а для дейтаграммы UDP.

Гнезда, которые используются для связи компьютеров друг с другом, должны быть одного типа и относиться к одному домену. Гнезда с установлением соединения взаимодействуют по следующей схеме: серверному гнезду назначается общеизвестный адрес, и оно непрерывно ожидает клиентских сообщений. Назначать адреса клиентским гнездам не нужно. Гнезда без установления соединения взаимодействуют следующим образом: каждому гнезду назначается адрес, и процесс может посылать данные другим процессам, используя адреса их гнезд.

Системные вызовы для работы с гнездами следующие: socket, bind, listen, accept, connect, send, sendto, recv, recvfrom, shutdown.

Смысл использования этих системных вызовов следующий.

Пусть гнездо — это телефонный аппарат. Системный вызов socket предназначен для покупки телефона в магазине. Системный вызов bind присваивает телефону номер. listen просит телефонную компанию подключить телефон к сети. connect звонит кому-то с Вашего телефона. Системные вызовы answer, accept отвечают на телефонный звонок. Системные вызовы send, recv разговаривают по телефону. Системный вызов shutdown кладет трубку после завершения разговора. Системный вызов close с дескриптором гнезда, полученным от accept — отказаться от услуг телефонной компании.

Последовательность вызовов гнезд, которые устанавливают между клиентом и сервером соединение типа виртуальный канал следующая:

Серверное гнездо                                 Клиентское гнездо

    socket                                                     socket

      bind                                                      connect

      listen                                                        

      accept                                         send       recv

send    recv

shutdown                                                  shutdown

      close                                                     close

Последовательность вызовов гнезд, которые устанавливают между клиентом и сервером соединение дейтаграммного типа следующая:

Серверное гнездо                                 Клиентское гнездо

      socket                                                   socket

      bind                                                          

      [connect]                                              [connect]

sendto   recvfrom                            sendto [send] recvfrom [recv]

shutdown                                                             shutdown

      close                                                     close

 

Прототип функции socket выглядит следующим образом:

 

#include <sys/types.h>

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

 

Этот системный вызов создает для указанного пользователем домена гнездо заданного типа и с указанным протоколом.

Аргумент domain определяет правила именования гнезда и формат адреса, например AF_UNIX (домен UNIX), AF_INET (Internet-домен).

Аргумент type задает тип гнезда:

– SOCK_STREAM — виртуальный канал с предварительно установленным соединением;

– SOCK_DGRAM — межпроцессное взаимодействие с помощью дейтаграмм;

– SOCK_SEQPACKET — виртуальный канал с предварительно установленным соединением с возможностью передачи сообщений максимальной длины.

Аргумент protocol зависит от значения аргумента domain. Как правило, равен 0 и ядро само выбирает для указанного домена соответствующий протокол.

Системный вызов socket возвращает целочисленный дескриптор гнезда в случае успешного выполнения и -1 — иначе. Дескриптор гнезда — то же самое, что и дескриптор файла.

 

Прототип bind выглядит следующим образом:

 

int bind(int sid, struct sockaddr *addr, int len);

 

Этот системный вызов присваивает гнезду имя, т.е. осуществляет привязку к адресу. sid — дескриптор гнезда. Аргумент addr указывает на структуру, содержащую имя, которое должно быть присвоено гнезду. len задает размер структуры, на которую указывает addr. В частности, в случае гнезда домена UNIX присваиваемое имя представляет собой путевое UNIX-имя, а структура имеет такой вид:

 

struct sockaddr _ un

{

short family;

char path[];

};

 

Здесь поле addr.family = AF_UNIX, а поле addr.path = "путевое UNIX-имя". При успешном выполнении bind в файловой системе создается файл с заданным именем. Если гнездо больше не нужно, этот файл следует удалить командой unlink. Структура sockaddr_un определяется в заголовке <sys/un.h>.

В случае гнезда домена Internet присваиваемое имя состоит из хост-имени машины и номера порта:

 

struct sockaddr_in

{

short family;

ushort port;

struct in_addr addr;

}

 

Поле addr.family = AF_INET

addr.port = "номер порта"

addr.addr = "имя хост-машины"

 

Структура sockaddr_in определяется в заголовке <netinet/in.h>.

При успешном завершении системный вызов bind возвращает 0, в случае неудачи — -1.

 

Прототип системного вызова listen имеет следующий вид:

 

int listen(ind sid, int size);

 

Этот системный вызов вызывается серверным процессом для создания гнезда, ориентированного на установление соединения типа SOCK_STREAM или SOCK_SEQPACKET.

sid — дескриптор гнезда. size задает максимальное число запросов на установление соединения, обычно 5. Если size=0 – неограниченное число запросов.

При успешном выполнении системный вызов возвращает 0, при неудаче — -1.

 

Системный вызов connect вызывается в клиентском процессе для установления соединения с серверным гнездом. Его прототип:

 

int connect(int sid, struct sockaddr *addr, int len);

sid — дескриптор гнезда; addr — указатель на адрес объекта типа struct sockaddr, хранящего имя серверного гнезда, с которым должно быть установлено соединение; len задает размер объекта в байтах, на который указывает аргумент addr.

Если sid обозначает потоковое гнездо, то между клиентским (КГ) и серверными (СГ) гнездами устанавливается соединение с использованием виртуального канала. Потоковое гнездо клиента может соединяться с гнездом сервера только один раз.

Если sid обозначает дейтаграммное гнездо, то для всех последующих системных вызовов send, осуществляемых через это гнездо, устанавливается адрес по умолчанию. Путем соединения с гнездом, имеющим NULL-адрес, дейтаграммные гнезда могут разорвать соединение.

При успешном выполнении connect возвращает 0, а в случае неудачи — -1.

 

Системный вызов accept вызывается в серверном процессе для установления соединения с клиентским гнездом, которое осуществило системный вызов connect (можно ассоциировать с открытием файла на чтение/запись). Его прототип следующий:

 

int accept(int sid, struct sockaddr *addr, int len);

 

sid — дескриптор гнезда; addr — указатель на объект struct addr; в нем хранится имя клиентского гнезда, с которым устанавливает соединение серверное гнездо. Аргумент len изначально устанавливается равным максимальному размеру объекта, указанному addr. При возврате он содержит размер имени клиентского гнезда, на которое указывает addr. Если addr или len имеет значение NULL, этот системный вызов не передает имя клиентского гнезда обратно в вызывающий процесс.

В случае неудачи accept возвращает -1, в противном случае — дескриптор нового гнезда, с помощью которого серверный процесс может взаимодействовать с данным клиентом.

 

Прототип системного вызова send выглядит следующим образом:

 

int send(int sid, const char *buf, int len, int flag);

// ( write )

Этот системный вызов передает содержащееся в buf сообщение длиной len байтов в гнездо, заданное sid и соединенное с данным гнездом.

Аргумент flag равен 0 для обычных сообщений, MSG_OOB — для высокоприоритетных.

Системный вызов send возвращает число переданных байтов в случае успеха, -1 — иначе.

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

 

int sendto(int sid, const char *buf, int len, int flag,

      struct sockaddr *addr_p, int *len_p);

 

Прототип системного вызова recv выглядит соответствующим образом:

 

int recv(int sid, char *buf, int len, int flag);

// (read)

 

Этот системный вызов принимает сообщение через гнездо, указанное в sid. Принятое сообщение записывается в buf, а максимальный размер buf задается в len.

Системный вызов recv возвращает число байтов, записанных в buf, в случае успеха, и -1 — неудачи.

 

Системный вызов recvfrom делает то же самое, только при его вызове задаются аргументы addr_p и len_p, позволяющие узнать имя гнезда-отправителя.

 

int recvfrom(int sid, char *buf, int len, int flag, struct sockaddr *addr_p, int *len_p);

 

Системный вызов shutdown закрывает соединение между серверным гнездом и клиентским гнездом.

 

int shutdown(int sid, int mode);

 

mode может принимать следующие значения (режим закрытия):

– 0 — закрывает гнездо для чтения;

– 1 — закрывает гнездо для записи;

– 2 — закрывает гнездо для чтения и записи.

Возвращает в случае удачи 0, неудачи — -1.

Системные вызовы, которые могут понадобиться при работе с гнездами: gethostbyname, gethostbyaddr, htons(port), setsoc, setsockopt. Посмотреть или удалить гнезда можно командами ipcs, ipcrm.

 

Пример. Создание гнезд домена INET типа virtual circuit

Программа сервера.

 

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

int main()

{ struct sockaddr _ in addr ;  //здесь будет адрес будущего гнезда

struct hostent *hp;             //это - часть

char hostname[256];         //адреса

char buffer [2048];              //область памяти куда будет поступать информация от //клиента, и где будет формироваться информация для //клиента

int sid , sid _ fd ;                                       // гнездо и польз. дескриптор гнезда

//можно еще int s=1;                          //параметр гнезда в библиотеке гнезд

sid=socket(PF_INET, SOCK_STREAM, 0);   // получаем дескриптор гнезда

if (sid==-1) return –1;

 

bzero (( void *)& addr , sizeof ( addr ));      // очищаем поля структуры для адреса

gethostname ( hostname , 256);            // узнаем хост-имя своей машины

hp = gethostbyname ( hostname );                      // получаем информацию о хосте

bcopy (( void *) hp -> h _ addr , ( void *)& addr . sin _ addr , hp -> h _ length ); // заполнить //поле хоста

//можно addr.sin_addr.s_addr=inet_addr(“127.0.0.1”);

/* или

 

addr.sin_family=AF_INET;

addr.sin_port=htons(7500);

addr.sin_addr.s_addr=htonl(INADDR_ANY); - локальный IP адрес

setsockopt(sid,SOL_SOCKET, SO_REUSEADDR, (char *)&s, sizeof(s)); - разрешение повторного использования локальных адресов

*/

addr . sin _ port = htons (7500);                  // заполнить поле порта

addr . sin _ family = AF _ INET ;                   // заполнить поле семейства адресов

if(bind(sid, (struct sockaddr *)&addr,sizeof(addr))!=0)

printf (“ошибка bind \ n ”);                      //осуществляем привязку гнезда к адресу

if(listen(sid,0)!=0)

printf (“ошибка listen \ n ”);                     //устанавливаем готовность соединения //гнезда к принятию запросов

sid _ fd = accept ( sid ,0,0);                          //получить соединение гнезда (пользова //тельский дескриптор файла). Можно //читать из него ответы клиента и запи //сывать свои данные

read ( sid _ fd , buffer , sizeof ( buffer ));         //читаем ответы клиента и записываем в

// или send(sid_fd, buffer, sizeof(buffer), 0);      //buffer

write ( sid _ fd , buffer , sizeof ( buffer ));         //записываем информацию в гнездо кли//ента

// или recv(sid_fd, buffer, sizeof(buffer), 0);

close ( sid _ fd );                                          //закрываем дескрипторы

close ( sid );

}

Программа клиента.

 

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

int main(void)

struct sockaddr_in kaddr;                     //адрес запроса

struct hostent * hp ;                                          //используется для получения адреса

int sid ;                                                    //дескриптор гнезда

char buffer [2048];                                 //буфер для приема и отправки инфор-

//мации

sid=socket(AF_INET, SOCK_STREAM,0);    //получаем дескриптор гнезда

bzero (( void *)& kaddr , sizeof ( kaddr ));   // очищаем поля структуры для адреса

hp = gethostbyname ( IPhost );                   //поиск IP адреса хоста; IPhost – домен //ное имя или IP адрес компьютера, на //котором запущена программа сервера 

if(hp==NULL) {printf(“error\n”); exit(1);}

bcopy(hp->h_addr, (struct sockaddr *)&kaddr.sin_addr, hp->h_length);    //запол//нить поле хоста

//можно kaddr.sin_addr.s_addr=inet_addr(“127.0.0.1”);

 

kaddr . sin _ port = htons (7500);                 // заносим номер порта

kaddr . sin _ family = AF _ INET ;                 // заполняем поле семейства адресов

if ( sid , ( struct sockaddr *)& kaddr , sizeof ( kaddr ))!=0) //устанавливаем соединение

{ perror (“ошибка соединения с гнездом сервера”); exit (1);}//с гнездом сервера

 

read ( sid , buffer , sizeof ( buffer ));              //читаем информацию из гнезда сервера

// или send(sid, buffer, sizeof(buffer), 0);            //и записываем ее в buffer

write ( sid , buffer , sizeof ( buffer ));              //передаем информацию в гнездо сервера

// или recv(sid, buffer, sizeof(buffer), 0);           //из buffer

close ( sid );                                               //закрываем дескриптор гнезда

}

6. Варианты заданий к лабораторным работам

 

 

Вариант №1

 

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

Сервер. Выбрать из очереди сообщений, созданной клиентом, последнее сообщение. Определить в полученном списке процессов те процессы, которые находятся в оперативной памяти, а также общее число сообщений в очереди. Записать в стандартный файл вывода эти данные, после чего удалить очередь сообщений.

 

Вариант №2

 

Сервер. Создать гнездо домена UNIX типа datagram. Присвоить ему имя. Принять сообщение от клиентского гнезда. Записать в стандартный файл вывода имена тех файлов из принятого сообщения, размер которых не превышает 1 блока.

Клиент. Создать гнездо домена UNIX типа datagram. Передать сообщение в серверное гнездо обо всех файлах текущего каталога, написанных на языке программирования Си.

 

Вариант №3

Клиент. Создать очередь сообщений. Передать в эту очередь полное имя текущего каталога и список файлов текущего каталога, в которых встречается подстрока «define».

Сервер. Выбрать из очереди все сообщения. Отсортировать список файлов из очереди по времени создания и записать эту информацию в стандартный файл вывода. Определить идентификатор процесса, который последним передал сообщение в очередь и максимальную длину очереди сообщений в байтах. Удалить очередь сообщений.

 

Вариант №4

 

Сервер. Создать разделяемую область памяти. Подсоединить её к виртуальному адресному пространству процесса. Записать в неё информацию обо всех файлах текущего каталога.

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

 

Вариант №5

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

Клиент. Записать, в созданную сервером разделяемую область памяти, список всех пользователей, работающих в настоящее время в системе.

 

Вариант №6

Клиент. Создать набор из десяти семафоров. Увеличивать за 1 цикл значение 1-го семафора на 1, 2-ого семафора на 2, …., 9-ого семафора на 9, а у 10-ого проверять значение на равенство 0.

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

Вариант №7

Клиент. Создать очередь сообщений. Передать в эту очередь информацию (имена) о текстовых файлах текущего каталога. Вывести на экран ответы сервера.

Сервер. Выбрать из очереди самое старое сообщение указанного типа. Определить те текстовые файлы, количество строк в которых превышает 10, и послать об этом сообщение клиенту. Определить время, когда в очередь было передано самое последнее сообщение.

 

Вариант №8

 

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

Клиент. Записать в созданную сервером разделяемую область памяти информацию (имена) обо всех файлах текущего каталога. После того, как будет получена информация о правах владельца файлов, вывести время, когда процесс последний раз подключался к разделяемой области памяти.

 

Вариант №9

Сервер. Создать гнездо домена UNIX типа virtual circuit. Присвоить ему имя. Принять сообщение от клиентского гнезда. Распечатать электронную почту 1-го по порядку пользователя, имя которого упоминается в ответе клиента.

Клиент. Создать гнездо домена UNIX типа virtual circuit. Передать в серверное гнездо информацию (имена) обо всех пользователях, от которых получена электронная почта.

 

Вариант №10

Клиент. Создать набор из пяти семафоров. Присвоить семафорам из созданного набора значения 10, 20, 30, 40, 50.

Сервер. Записать в стандартный файл вывода значение 3-его семафора из указанного набора, после чего уменьшить его значение на –5. Вывести также значение идентификатора процесса, который выполнял операции над 1-ым семафором последним.

 

Вариант №11

Сервер. Создать гнездо домена INET типа virtual circuit. Присвоить ему имя. Записать в него информацию, содержащую имена файлов текущего каталога, которые были модифицированы в течении последнего месяца. Распечатать ответ клиента.

Клиент. Создать гнездо домена INET типа virtual circuit. Прочитать сообщение из серверного гнезда. Определить имена файлов, которые нельзя выполнять для данного пользователя и отправить их в виде сообщения в серверное гнездо.

 

Вариант №12

Сервер. Создать разделяемую область памяти. Подсоединить её к виртуальному адресному пространству процесса. Записать в неё информацию (идентификаторы) обо всех активных процессах в системе, управляемых терминалами.

Клиент. Открыть разделяемую область памяти, созданную серверным процессом. Считать из неё информацию. Определить состояния процессов, идентификаторы которых указаны в сообщении. Определить также количество процессов, подсоединенных в данный момент времени к разделяемой области памяти.

Вариант №13

Сервер. Создать гнездо без установления соединения домена UNIX. Присвоить ему имя. Записать в него информацию о количестве файлов текущего каталога. Распечатать информацию, полученную от клиента.

Клиент. Создать гнездо без установления соединения домена UNIX. Прочитать сообщение из серверного гнезда. Уменьшить прочитанное значение на число, равное количеству файлов, имя которых начинается с точки и передать это значение в гнездо сервера.

 

Вариант №14

Сервер. Создать очередь сообщений. Записать в неё сообщение об именах файлов, помещенных в спулинг.

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

 

Вариант №15

Сервер. Создать гнездо с установлением соединения домена INET. Присвоить ему имя. При поступлении клиентского сообщения о календаре текущего месяца, определить текущий день недели по текущей дате.

Клиент. Создать гнездо с установлением соединения домена INET. Переслать в серверное гнездо сообщение, содержащее календарь текущего месяца.

 

Вариант №16

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

Клиент 1. Записать в разделяемую область памяти, созданную сервером, имена текстовых файлов текущего каталога. Записать в стандартный файл вывода результаты обработки сервера.

Клиент 2. Записать в разделяемую область памяти, созданную сервером, имена файлов текущего каталога, написанные на языке программирования Си. Записать в стандартный файл вывода результаты обработки этого запроса.

 

Вариант №17

Сервер. Создать очередь сообщений. Записать в качестве 1-го сообщения текущую дату и время, в качестве 2-го сообщения – имена всех пользователей, работающих в настоящее время в системе, в качестве 3-его сообщения – хост-имя компьютера. Сообщения, полученные от клиентов, распечатывать.

Клиент 1. Выбрать из очереди сообщений 2-ое сообщение и определить имена терминалов, связанных с этим пользователем.

Клиент 2. Выбрать из очереди 1-ое сообщение, определить по нему день недели, а также записать эту информацию в очередь сообщений.

Вариант №18

Сервер. Создать гнездо безустановления соединения домена UNIX. Присвоить ему адрес. Послать в клиентское гнездо данные (идентификаторы) обо всех активных процессах системы. Результаты обработки клиентом этих данных распечатать.

Клиент. Создать гнездо без установления соединения домена UNIX. Отфильтровать информацию из серверного гнезда с целью выявления тех процессов, которые принадлежат данному пользователю. Результаты обработки передать в серверное гнездо.

 

 

Вариант №19

Сервер. Создать гнездо домена UNIX типа virtual circuit. Назначить ему адрес. Среди поступивших от клиентов сообщений, отфильтровать такие, которые содержат шаблон «S».

Клиент 1. Создать гнездо домена UNIX типа virtual circuit. Послать в серверное гнездо сообщение, содержащее полную информацию о списке всех активных процессов в системе не управляемых терминалами.

Клиент 2. Создать гнездо домена UNIX типа virtual circuit. Послать в серверное гнездо сообщение, содержащее полную информацию о списке всех активных процессов в системе управляемых терминалами.

 

Вариант №20

Сервер. Создать набор из 6-ти семафоров. Присвоить семафорам из созданного набора значения 0, 1, 2, …, 5. В течении 2-х минут распечатывать значения семафоров, а потом удалить этот набор семафоров.

Клиент 1. Изменить значения из набора семафоров на { +1, +2, +3, …, +6}.

Клиент 2. Уменьшитьзначения семафоров из набора в 2 раза.

 

Вариант №21

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

Клиент 1. Подсоединиться к разделяемой области памяти. Определить подкаталог родительского каталога с максимальным количеством файлов и записать эту информацию в разделяемую область памяти.

Клиент 2. Подсоединиться к разделяемой области памяти. Определить количество процессов, подсоединенных к разделяемой области памяти и записать эту информацию в неё.

 

Вариант №22

Сервер. Создать очередь сообщений. Записать в качестве 1-го сообщения количество пользователей, работающих в настоящее время в системе, в качестве 2-ого сообщения – имена этих пользователей, в качестве 3-его сообщения – сумарное рабочее время, затраченное пользователями, в качестве 4-ого сообщения – имена задействованных терминалов.

Клиент 1. Определить общее число байтов во всех сообщениях очереди.

Клиент 2. Определить идентификатор процесса, который последним передал в очередь сообщение.

Клиент 3. Прочитать 3-е сообщение из очереди и вывести его на печать.

 

Вариант №23

Сервер. Создать гнездо без установления соединения. Присвоить ему имя. При поступлении клиентского сообщения определить системную составляющую приоритета полученных процессов и переслать клиенту.

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

 

Вариант №24

Сервер. Создать разделяемую область памяти и набор семафоров. Ждать сообщений клиентов. При поступлении сообщения от 1-ого клиента, обработать его и переслать абоненту размеры полученных файлов. Распечатать содержимое спулинга, полученное от 2-ого клиента.

Клиент 1. Записать в разделяемую область памяти имена тех файлов текущего каталога, в которых встречается строка с шаблоном «main». Распечатать ответ сервера.

Клиент 2. Записать в разделяемую область памяти содержимое спулинга.

 

Вариант №25

Сервер. Создать гнездо с установлением соединения домена INET. Присвоить ему имя. При поступлении клиентского сообщения, определить количество файлов в каждой поддиректории текущего каталога и переслать эту информацию в клиентское гнездо.

Клиент. Создать гнездо с установлением соединения INET. Переслать в серверное гнездо сообщение обо всех поддиректориях текущего каталога. Записать в стандартный файл вывода ответ сервера.

 

Вариант №26

Сервер. Создать очередь сообщений. Записать в качестве 1-ого сообщения имена всех текстовых файлов текущего каталога, в качестве 2-ого сообщения – имена всех файлов текущего каталога, написанных на языке программирования Си, в качестве 3-его сообщения – имена всех двоичных файлов текущего каталога.

Клиент 1. Прочитать 2-ое сообщение из очереди и определить количество строк в каждом файле.

Клиент 2. Определить время, когда последнее сообщение было записано в очередь и вывести его на экран

 

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

1. Чан Т. Системное программирование на С++ для UNIX. – Киев: Издательская группа BHV, 1999 г.

2. Моли Б. UNIX/LINUX: Теория и практика программирования. - М: КУДИЦ_ОБРАЗ, 2004 г.

3. Роббинс А. LINUX: программирование в примерах. – М: КУДИЦ_ОБРАЗ, 2005 г.

 

 


Дата добавления: 2019-02-13; просмотров: 268; Мы поможем в написании вашей работы!

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






Мы поможем в написании ваших работ!