Создание параллельного многопроцессного сервера с установлением логического соединения TCP 


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



ЗНАЕТЕ ЛИ ВЫ?

Создание параллельного многопроцессного сервера с установлением логического соединения TCP



Цель работы: изучить методы создания серверов с установлением логи- ческого соединения TCP, используя алгоритм параллельной обработки запро- сов, основанный на многопроцессности.

 

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

 

Основные сведения о процессах

В некоторых операционных системах (например ОС Linux) управление процессами является ключевой технологией при разработке многих программ.

Процесс – это находящаяся в состоянии выполнения программа, вклю- чающая ее среду выполнения.

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

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

Возможны следующие состояния процесса: S – неактивный (спящий) процесс;

SW – процесс выгружен на устройство выгрузки; R – активный (выполняющийся) процесс;

Z – ''зомби'' (процесс является завершенным, однако он не послал статус возврата в родительский процесс);

T – процесс остановлен.

 

Создание процессов

Cоздать новый процесс в ОС Linux можно с помощью системного вызова функции fork (). Синтаксис вызова следующий:


#include <sys/types> #include <unistd.h> pid_t fork(void);

 

pid _t является примитивным типом данных, который определяет иденти- фикатор процесса или группы процессов. При вызове fork () порождается новый процесс (процесс-потомок), который почти идентичен порождающему процес- су-родителю.

Процесс-потомок наследует следующие признаки родителя:

· сегменты кода, данных и стека программы;

· таблицу файлов, в которой находятся состояния флагов дескрипторов файла, указывающие, читается ли файл или пишется. Кроме того, в таблице файлов содержится текущая позиция указателя записи-чтения;

· рабочий и корневой каталоги;

· реальный и эффективный номер пользователя и номер группы;

· приоритеты процесса (администратор может изменить их через nice);

· контрольный терминал;

· маска сигналов;

· ограничения по ресурсам;

· сведения о среде выполнения;

· разделяемые сегменты памяти.

Потомок не получает от родителя следующие признаки:

· идентификатор процесса (PID, PPID);

· израсходованное время ЦП (оно обнуляется);

· сигналы процесса-родителя, требующие ответа;

· блокированные файлы (record locking).

При вызове fork () возникают два полностью идентичных процесса. Весь код после fork () выполняется дважды: как в процессе-потомке, так и в процессе- родителе.

Процесс-потомок и процесс-родитель получают разные коды возврата по- сле вызова fork (). Процесс-родитель получает идентификатор (PID) потомка. Если это значение будет отрицательным, значит, при порождении процесса произошла ошибка. Процесс-потомок получает в качестве кода возврата значе- ние 0, если вызов fork () произошел успешно.

Таким образом, можно проверить, был ли создан новый процесс.

 

switch(ret=fork()){

case -1: /{*}при вызове fork() возникла ошибка{*}/ case 0: /{*}это код потомка{*}/

default: /{*}это код родительского процесса{*}/

}


Различие между процессами и потоками

Изучив сущность и основные методы создания и работы с процессами и потоками, приведем основные различия между ними:

– поток представляет собой облегченную версию процесса. Чтобы понять, в чем состоит его особенность, необходимо привести основные характеристики процесса;

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

– процесс подвержен диспетчеризации. Он определяет порядок выполне- ния одной или нескольких программ, при этом выполнение может перекры- ваться с другими процессами. Каждый процесс имеет состояние выполнения и приоритет диспетчеризации.

Если рассматривать эти характеристики независимо друг от друга (как это принято в современной теории операционных систем), то:

- владелец ресурса обычно называется процессом или задачей. Ему при- сущи:

· виртуальное адресное пространство;

· индивидуальный доступ к процессору, другим процессам, файлам, и ресурсам ввода – вывода.

- модуль для диспетчеризации обычно называется потоком или облег- ченным процессом. Ему присущи:

· состояние выполнения (активное, готовность и т.д.);

· сохранение контекста потока в неактивном состоянии;

· стек выполнения и некоторая статическая память для локаль- ных переменных;

· доступ к пространству памяти и ресурсам своего процесса.

 

Все потоки процесса разделяют общие ресурсы. Изменения, вызванные одним потоком, становятся немедленно доступны другим потокам.

При корректной реализации потоки имеют определенные преимущества над процессами. Им требуется меньше времени:

· для создания нового потока, поскольку создаваемый поток использует адресное пространство текущего процесса;

· для завершения потока;

· для переключения между двумя потоками в пределах того же самого процесса.

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


Алгоритм работы параллельного (многопроцессного) сервера с установлением логического соединения

Приведем обобщенный алгоритм работы параллельного (многопроцесс- ного) сервера с установлением логического соединения:

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

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

3. Ведущий процесс. Вызывать в цикле функцию accept для получения очередного запроса от клиента и создавать новый ведомый процесс через fork.

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

5. Ведомый процесс. Выполнять обмен данными с клиентом через соеди- нение: принимать запрос (запросы) и передавать ответ (ответы).

6. Ведомый процесс. Закрыть соединение и завершить работу. Ведомый процесс завершает свою работу после обработки всех запросов от одного кли- ента.

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

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


 

Рисунок 5 – Схема организации процессов параллельного сервера с установлением логического соединения, в котором используются однопотоковые процессы

 

Методические указания по созданию параллельного сервера с установлением логического соединения TCP, использующего отдельный процесс для обработки запросов клиента

Рассмотрим последовательность действий по созданию такого сервера на конкретном примере.

Осуществить взаимодействие клиента и сервера на основе протокола TCP. Реализовать параллельное соединение с использованием многопроцессно- сти. На сервере хранится список сотрудников фирмы. Каждая запись списка со- держит следующую информацию о сотрудниках:

- ФИО сотрудника;

- табельный номер;

- доход в месяц;

- ставка налогов, отчисляемых в бюджет. Таких записей должно быть не менее пяти.

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


Решение этой задачи подразумевает использование компилятора языка С++ gcc, поставляемого вместе с эмулятором операционной системы Unix – Cygwin.

Для реализации поставленной задачи, как и ранее, создадим два проекта, для отладки и компиляции которых используем оболочку Cygwin.

 

Серверная часть

 

// Подключение необходимых библиотек для работы с пакетом

//Cygwin

#include <sys/types.h> #include<sys/socket.h> #include<sys/signal.h> #include<sys/wait.h> #include<sys/resource.h> #include<netinet/in.h>

 

#include <string.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h>

 

 

struct Employee{

char name[35]; char number[10]; char income[10]; char tax[4];

} em[5];

 

// процедура для обслуживания соединения int Func(int newS){

long int i,num,t, mon, doh, nal; float sum;

int m;

char p,p1,s;

char buf[256],b[256]; while (true){

recv(newS,buf,sizeof(buf),0); p=buf[0];

switch(p){ case '1':

buf[0]='\0'; sum=0;

recv(newS,buf,sizeof(buf),0); mon=atoi(buf); recv(newS,buf,sizeof(buf),0); s=buf[0];

for (i=1;i<=5;i++)

if (em[i].name[0]==s){


nal=atoi(em[i].tax); doh=atoi(em[i].income); printf("mon %d\n",mon); sum=sum+(nal*doh*mon)/100.0;

}

int* decpt,*sgn; printf("%f\n",sum); strcpy(buf,fcvt(sum,3,decpt,sgn)); send(newS,buf,sizeof(buf),0); puts(buf);

break; case '2':

recv(newS,buf,sizeof(buf),0);// Номер num=atoi(buf);

printf("%d\n",num); recv(newS,buf,sizeof(buf),0); p1=buf[0];

switch(p1){

case '1':

recv(newS,buf,sizeof(buf),0);// Имя strcpy(em[num].name,buf);

break; case '2':

recv(newS,buf,sizeof(buf),0);//Таб.номер strcpy(em[num].number,buf);

break; case '3':

recv(newS,buf,sizeof(buf),0);//Доход strcpy(em[num].income,buf);

break; case '4':

recv(newS,buf,sizeof(buf),0);//Ставка налога

strcpy(em[num].tax,buf);

 

}

break; case '3':

for (i=1;i<=5;i++){ buf[0]='\0';

strcat(buf,em[i].name);strcat(buf," ");

strcat(buf,em[i].number);strcat(buf," ");

strcat(buf,em[i].income);strcat(buf," ");

strcat(buf,em[i].tax);strcat(buf,"\n"); send(newS,buf,sizeof(buf),0);

}

break; case '4':

exit(0);

}

}

}


Поскольку в параллельных серверах для динамического создания процес- сов используется функция fork () (см. ниже), они являются потенциальным ис- точником проблемы не полностью завершившихся процессов (процессов, ин- формация о которых остается в системных таблицах). В системе Linux эта про- блема решается путем передачи специального сигнала родительскому процессу после завершения работы каждого дочернего процесса. Завершившийся про- цесс остается в виде так называемого процесса-зомби до тех пор, пока роди- тельским процессом не будет выполнен системный вызов wait 3. Для полного завершения дочернего процесса (т.е. для уничтожения процесса-зомби) в рас- сматриваемом примере перехватывается сигнал завершения дочернего процесса и выполняется функция обработки этого сигнала. Операционной системе дается указание о том, что для ведущего процесса сервера при получении каждого сигнала о завершении работы дочернего процесса (сигнал SIGCHLD) должна быть выполнена функция reaper () в виде следующего вызова, который в нашей программе осуществляется в main:

 

signal (SIGCHLD, reaper);

 

После вызова функции signal () система автоматически вызывает функцию

reaper () при получении процессом сервера каждого сигнала SIGCHLD.

Функция reaper () вызывает системную функцию wait 3() для полного за- вершения дочернего процесса, закончившего свою работу. Функция wait 3() ос- тается заблокированной до тех пор, пока не произойдет завершение работы од- ного или нескольких дочерних процесса (по любой причине). Эта функция воз- вращает значение структуры status, которую можно проанализировать для по- лучения дополнительной информации о завершившемся процессе. Поскольку данная программа вызывает функцию wait 3() при получении сигнала SIGCHLD, вызов этой функции всегда происходит только после завершения ра- боты дочернего процесса. Для предотвращения возникновения в сервере тупи- ковой ситуации в случае ошибочного вызова в программе используется пара- метр WNOHANG, который указывает, что функция wait 3 не должна блокиро- ваться в ожидании завершения какого-либо процесса. Вместо этого возврат управления после вызова происходит немедленно, даже если не произошел вы- ход из какого-либо процесса.

 

void reaper(int sig){ int status;

while (wait3(&status,WNOHANG,(struct rusage*)0)>=0);

}

 

int main(){

strcpy(em[1].name,"Sergeev Sergei Sergeevich"); strcpy(em[1].number,"1"); strcpy(em[1].income,"100000"); strcpy(em[1].tax,"10");


strcpy(em[2].name,"Ivanov Ivan Ivanovich"); strcpy(em[2].number,"2"); strcpy(em[2].income,"200000"); strcpy(em[2].tax,"20");

 

strcpy(em[3].name,"Vladimirov Vladimir Vladimirovich"); strcpy(em[3].number,"3"); strcpy(em[3].income,"300000"); strcpy(em[3].tax,"30");

 

 

strcpy(em[4].name,"Sidorov Sidor Sidorovich "); strcpy(em[4].number,"4"); strcpy(em[4].income,"400000"); strcpy(em[4].tax,"40");

 

strcpy(em[5].name,"Vasilev Vasilii Vasilievich"); strcpy(em[5].number,"5"); strcpy(em[5].income,"500000"); strcpy(em[5].tax,"50");

 

struct sockaddr_in local; int s,

newS, rc;

 

local.sin_family=AF_INET; local.sin_port=htons(7500); local.sin_addr.s_addr=htonl(INADDR_ANY);

 

s=socket(AF_INET, SOCK_STREAM,0);

rc=bind(s,(struct sockaddr *)&local, sizeof(local)); rc=listen(s,5);

(void)signal(SIGCHLD,reaper); while(true){

newS=accept(s,NULL,NULL); switch (fork()){

case 0:

(void)close(s); exit(Func(newS));

default:

(void)close(newS);

}

}

return 0;

}

 

Клиентская часть

 

#include <sys/types.h>


#include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<stdio.h> #include <stdlib.h> #include <string.h>

 

int main(){

 

struct sockaddr_in peer; int s,t,t1;

int rc;

char buf[256],p,p1,b[256];;

 

peer.sin_family=AF_INET; peer.sin_port=htons(7500); peer.sin_addr.s_addr=inet_addr("127.0.0.1");

 

s=socket(AF_INET,SOCK_STREAM,0);

rc=connect(s,(struct sockaddr *)&peer,sizeof(peer)); while(true){

//Выбор пункта меню и отправка его серверу puts("Choose:");

puts("\t1 - Select");

puts("\t2 - Edit");

puts("\t3 - View");

puts("\t4 - Exit");

scanf("%s",buf);

buf[1]='\0'; send(s,buf,sizeof(buf),0); p=buf[0];

 

switch (p){

case '1'://Выбрать

puts("kol-vo months (1-12):");scanf("%s",buf); send(s,buf,sizeof(buf),0);

puts("Symbol: ");scanf("%s",buf); send(s,buf,sizeof(buf),0);

 

printf("Sum of taxes: "); recv(s,buf,sizeof(buf),0);

for (t=0;buf[t+3];t++) printf("%c",buf[t]); printf(".");

for (t1=t;buf[t1];t1++) printf("%c",buf[t1]); printf("\n");

break;

case '2'://Подредактировать puts("What number (1-5) to edit");

scanf("%s",buf);//Какой номер будем редактировать send(s,buf,sizeof(buf),0);

 

puts("What field (1-4) to edit");


puts("\t1 - Name");

puts("\t2 - Number");

puts("\t3 - Income");

puts("\t4 - Tax");

scanf("%s",buf);

send(s,buf,sizeof(buf),0); p1=buf[0];

buf[0]='\0';

switch(p1){   //Введите новые поля case '1':printf("Name: ");

fflush(stdin);fflush(stdout); scanf("%s",b);strcat(buf,b);strcat(buf," ");

scanf("%s",b);strcat(buf,b);strcat(buf," ");

scanf("%s",b);strcat(buf,b);strcat(buf,"\0"); send(s,buf,sizeof(buf),0);

break;

case '2':fflush(stdin);fflush(stdout); printf("Tab Number: ");scanf("%s",buf); send(s,buf,sizeof(buf),0);

break;

case '3':fflush(stdin);fflush(stdout); printf("Income per month: "); scanf("%s",buf);

send(s,buf,sizeof(buf),0); break;

case '4':fflush(stdin);fflush(stdout); printf("Tax rate (%) per month: "); scanf("%s",buf);

send(s,buf,sizeof(buf),0);

}

break;

case '3'://Просмотреть 5 записей recv(s,buf,sizeof(buf),0);printf("%s",buf);

recv(s,buf,sizeof(buf),0);printf("%s",buf);

recv(s,buf,sizeof(buf),0);printf("%s",buf);

recv(s,buf,sizeof(buf),0);printf("%s",buf);

recv(s,buf,sizeof(buf),0);printf("%s",buf); break;

case '4'://Выход

exit(0);

 

}

}

}

 

 

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


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

После возврата управления из функции accept () ведущий процесс сервера создает ведомый процесс для обслуживания соединения. Для этого ведущий процесс вызывает функцию fork (), чтобы разделиться на два процесса. Поток во вновь созданном дочернем процессе вначале закрывает сокет ведущего процес- са, а затем вызывает функцию Func () для обслуживания соединения. Поток в родительском процессе закрывает сокет, который был создан для обслуживания нового соединения, и продолжает выполнение бесконечного цикла. При сле- дующем проходе по циклу ведущий процесс после вызова функции accept () снова переходит в состояние ожидания очередных запросов на установление соединения. Следует отметить, что и первоначальный, и новые процессы имеют доступ к открытым сокетам после вызова функции fork (), и они оба должны за- крыть один из этих сокетов, после чего система освобождает связанный с ним ресурс. Поэтому этот сокет закрывается только в ведущем процессе после вы- зова функции close () потоком ведущего процесса для закрытия сокета нового соединения. Аналогичным образом, когда поток в ведомом процессе вызывает функцию close () для закрытия сокета ведущего процесса, этот сокет закрывает- ся только в ведомом процессе. Ведомый процесс продолжает получать доступ к сокету нового соединения до тех пор, пока не завершит свою работу, а ведущий сервер продолжает иметь доступ к сокету, который соответствует общеприня- тому порту.

После закрытия сокета ведущего процесса ведомый процесс вызывает процедуру Func (). После возврата управления процедурой Func () ведомый про- цесс использует возвращенное значение в качестве параметра вызова функции exit. Система Linux интерпретирует вызов функции exit как требование завер- шить процесс и использует параметр вызова этой функции как код завершения процесса. В соответствии с общепринятым соглашением в процессе для обо- значения нормального завершения используется код завершения нуль. После прекращения работы ведомого процесса операционная система автоматически закрывает все его открытые дескрипторы, в том числе дескриптор соединения ТСР.

 

Индивидуальные задания

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


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

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

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

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

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

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

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

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


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

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

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

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

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

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

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


Контрольные вопросы

1. Какие преимущества предоставляет параллельная реализация сервера?

2. Какие основные задачи выполняет ведущий процесс?

3. Для чего используется блокирующий вызов функции accept ()?

4. Когда и для чего вызывается функция fork ()?

5. Каким образом решается проблема не полностью завершившихся про- цессов (процессов, информация о которых остается в системных таблицах)?

6. Какой код используется в процессе для обозначения нормального за- вершения?


ЛАБОРАТОРНАЯ РАБОТА №5



Поделиться:


Последнее изменение этой страницы: 2019-12-15; просмотров: 562; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.117.196.217 (0.172 с.)