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

OperationSystems

.pdf
Скачиваний:
11
Добавлен:
02.04.2015
Размер:
752.19 Кб
Скачать

Если сокет ориентирован на режим с установлением соединения (имеет тип SOCK_STREAM), то, воспользовавшись функцией listen () (листинг 14), его следует пометить как готового принимать соединения («слушающего»).

Листинг 14:

#include <sys/socket.h>

int listen (int sd, int backlog)

Аргумент backlog сообщает операционной системе рекомендуемую длину очереди соединений, ожидающих обработки слушающим сокетом. Реализация должна поддерживать значения аргумента backlog, вплоть до конфигурационной константы SOMAXCONN, определенной в заголовочном файле <sys/socket.h>. ОС имеет право установить длину очереди меньше рекомендуемой. При неположительном значении backlog очередь будет иметь зависящую от реализации минимальную длину.

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

Листинг 15:

#include <sys/socket.h>

int accept (int sd, struct sockaddr *restrict address, socklen_t *restrict address_len);

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

Если очередь соединений, ожидающих обработки слушающим сокетом, пуста и для дескриптора sd не установлен флаг O_NONBLOCK, то вызвавший функцию ассерt () процесс (поток управления) блокируется до появления подобного соединения. При непустой очереди функция select () сообщит о готовности дескриптора sd к чтению.

Другая сторона, т.е. потенциальный партнер по взаимодействию, инициирует соединение с помощью функции соnnесt () (листинг 16). Аргументы address и address_len стандартным образом задают адрес сокета (как правило, слушающего), с которым необходимо установить соединение.

Листинг 16:

#include <sys/socket.h>

int connect (int sd, struct sockaddr *restrict address, socklen_t *restrict address_len);

Если для сокета, заданного аргументом sd (запрашивающего установление соединения), еще не выполнена привязка к локальному адресу, функция connect () сама осуществит связывание со свободным локальным адресом (правда, лишь при условии, что адресное семейство сокета отлично от AF_UNIX).

Функция connect () ограничится фиксацией адреса сокета, взаимодействующего с заданным аргументом sd, если тип сокета не требует установления соединения. В частности, для сокетов типа SOCK_DGRAM таким способом можно специфицировать

адреса отправляемых (с помощью функции send ()) и принимаемых (посредством обращения к функции recv ()) датаграмм.

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

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

Если для дескриптора sd задан флаг O_NONBLOCK, а соединение не может быть установлено немедленно, то вызов connect () завершается неудачей со значением errno, равным EINPROGRESS, но установление соединения продолжается и будет завершено асинхронно. Последующие обращения к функции connect () с тем же сокетом, выполненные до установления соединения, завершаются неудачей (EALREADY).

Сокет оказывается в неспецифицированном состоянии, если функция connect () завершается неудачей по другим причинам. Приложения, соответствующие стандарту Р0SIХ-2001, должны закрыть файловый дескриптор sd и создать новый сокет для продолжения попыток установить соединение.

После асинхронного установления соединения функции select () и роll () сообщат, что файловый дескриптор sd готов к записи.

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

Листинг 17:

#include <sys/socket.h>

ssize_t recvfrom (int sd, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len); ssize_t recv (int sd, void *buffer, size_t length, int flags);

ssize_t recvmsg (int sd, struct msghdr *message, int flags); ssize_t sendto (int sd, const void *message, size_t length,

int flags, const struct sockaddr *dest_addr, socklen_t dest_len); ssize_t send (int sd, const void *buffer, size_t length, int flags); ssize_t sendmsg (int sd, const struct msghdr *message, int flags);

Функция recvfrom () позволяет прочитать данные (в рассматриваемом контексте называемые также сообщением) из сокета с дескриптором sd и поместить их в буфер buffer длины length. Обычно функцию recvfrom () применяют к сокетам, ориентированным на режим без установления соединения, поскольку она выдает исходный адрес в структуре типа sockaddr.

В число возможных составляющих значения аргумента flags входят следующие флаги:

MSG_PEEK - не удалять прочитанные данные. Следующий вызов recvfrom () или другой функции ввода снова вернет их;

MSG_WAITALL - для сокетов типа SOCK_STREAM флаг означает, что вызывающий процесс блокируется до получения всего запрошенного объема данных (а не до прихода первого сообщения);

MSG_OOB - запрашиваются экстренные данные. Трактовка этого понятия зависит от протокола.

Как и положено функции ввода, в результате recvfrom () возвращает количество прочитанных и помещенных в буфер данных. Для сокетов, учитывающих границы сообщений (SOCK_RAW, SOCK_DGRAM, SOCK_SEQPACKET), за одно обращение читается все сообщение; если оно не помещается в буфер, лишние байты (в отсутствие флага MSG_PEEK) отбрасываются.

Формально можно считать, что функция recv () эквивалентна recvfrom () с нулевым значением аргумента address_len. Поскольку она не позволяет узнать исходный адрес, ее обычно используют для сокетов, установивших соединение. (Можно провести и еще одну аналогию: если пренебречь флагами, функция recv () эквивалентна read ()).

По сравнению с recv (), более содержательным аналогом функции recvfrom () является recvmsg (). Отличия в данном случае носят скорее синтаксический характер и по сути сводятся к способу передачи входных значений и возврата результатов: для минимизации числа аргументов функция recvmsg () использует структуру типа msghdr.

Подобно тому, как write () составляет пару read (), функцию sendto () можно считать парной по отношению к recvfrom (). Она предназначена для отправки через сокет sd сообщения, заданного аргументами message и length, по адресу dest_addr длины dest_len. Если для сокета установлено соединение, целевой адрес dest_addr игнорируется.

В число возможных составляющих значения аргумента flags входят следующие флаги:

MSG_EOR - обозначает границу записи (если это понятие поддерживается протоколом);

MSG_OOB - отправляются экстренные данные.

Разумеется, успешное завершение функции sendto () не гарантирует доставку сообщения. Результат, равный -1, указывает только на локально выявляемые ошибки.

Функция send () – пара для recv () со всеми следующими из этого обстоятельства эквивалентностями и аналогиями.

Для функции sendmsg () структура типа msghdr, на которую указывает аргумент message, является входной (что показывает спецификатор const). В поле msg_name задается целевой адрес. Поле msg_f lags игнорируется.

Для завершения операций приема и/или отправки данных через сокет служит функция shutdown () (листинг 18).

Листинг 18:

#include <sys/socket.h>

int shutdown (int sd, int how);

Значение аргумента how показывает, что именно завершается: SHUT_RD прекращает прием, SHUT_WR – отправку, SHUT_RDWR – и то, и другое.

1.3.2.Пример модуля сервера

#include <sys/socket.h> #include <iostream> #include <ctime> #include <sys/types.h> #include <netinet/in.h>

int main()

{

int ip[4] = {127, 0, 0, 1}; int port = 10000;

char buffer[32]; char buf[3];

int bytes = 1;

struct sockaddr_in ssin; int labsocket;

int AcceptSocket; int sides[3];

for(int i = 0; i < 32; i++)

{

buffer[i] = '\0';

}

//открытие сокета

labsocket = socket(AF_INET, SOCK_STREAM, 0); if(labsocket < 0)

{

std::cout<<"Error, can't open socket\n"; exit(0);

}

//установка ip и порта ssin.sin_family = AF_INET;

ssin.sin_addr.s_addr = htonl(INADDR_ANY); ssin.sin_port = htons(port);

if(bind(labsocket, (sockaddr *)&ssin, sizeof(ssin)) == -1)

{

std::cout<<"Error, can't bind socket\n"; exit(0);

}

if(listen(labsocket, 1) == -1)

{

std::cout<<"Error listening on socket\n"; exit(0);

}

std::cout<<"Waiting for a client to connect...\n"; while(true)

{

AcceptSocket = -1; while(AcceptSocket == -1)

{

AcceptSocket = accept( labsocket, NULL, NULL );

}

std::cout<<"Client Connected\n"; labsocket = AcceptSocket; break;

}

while(bytes < 0)

{

bytes = recv(labsocket, buffer, 1024, 0 );

}

if (!bytes)

{

std::cout<<"Connection closed\n"; system("pause");

exit(0);

}

else

{

std::cout<<bytes<<" bytes recived, "<<buffer<<"\n";

}

bytes = send( labsocket, buffer, strlen(buffer)+1, 0 ); std::cout<<bytes<<" bytes sent\n";

return 0;

}

1.3.3.Пример модуля клиента

#include <sys/socket.h> #include <iostream> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h>

int main()

{

int port = 10000; char buffer[1024]; int bytes = 1;

struct sockaddr_in ssin; int labsocket; //открытие сокета

labsocket = socket(AF_INET, SOCK_STREAM, 0); if(labsocket < 0)

{

std::cout<<"Error, can't open socket\n"; exit(0);

}

//установка ip и порта ssin.sin_family = AF_INET;

ssin.sin_addr.s_addr = inet_addr("127.0.0.1"); ssin.sin_port = htons(port);

if(connect(labsocket, (sockaddr *)&ssin, sizeof(ssin)) == -1)

{

std::cout<<"Error, can't connect to server\n"; exit(0);

}

std::cout<<"Enter m\n"; std::cin>>buffer;

bytes = send( labsocket, buffer, strlen(buffer)+1, 0 ); std::cout<<bytes<<" bytes sent\n";

bytes = recv(labsocket, buffer, 1024, 0 ); if (!bytes)

{

std::cout<<"Connection closed\n"; system("pause");

exit(0);

}

else

{

std::cout<<bytes<<" bytes recived, result - "<<buffer<<"\n";

}

return 0;

}

2.Задания на лабораторные работы

2.1. Лабораторная работа #4

Организовать взаимодействие типа клиент-сервер в ОС Windows.

При сдаче лабораторной работы необходимо продемонстрировать работу системы на нескольких компьютерах, объединенных в локальную сеть.

2.2. Лабораторная работа #5

Организовать взаимодействие типа клиент-сервер средствами POSIX.

3.Варианты заданий

3.1. Таблица вариантов заданий

Код представлен в виде X.Y, где X – протокол (1 – TCP, 2 - UDP), Y – номер задания из списка (п.3.2).

№ варианта

Код

№ варианта

Код

 

 

 

 

1

1.1

11

2.1

 

 

 

 

2

1.2

12

2.2

 

 

 

 

3

1.3

13

2.3

 

 

 

 

4

1.4

14

2.4

 

 

 

 

5

1.5

15

2.5

 

 

 

 

6

1.6

16

2.6

 

 

 

 

7

1.7

17

2.7

 

 

 

 

8

1.8

18

2.8

 

 

 

 

9

1.9

19

2.9

 

 

 

 

10

1.10

20

2.10

 

 

 

 

3.2.Задания

1.Клиент обращается к серверу на выполнение какой-либо команды. Сервер выполняет эту команду и возвращает результаты клиенту.

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

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

4.При подключении к серверу клиент должен ввести пароль. Разрешено сделать три попытки. Если пароль неверен, сервер должен блокировать IP-адрес клиента на 2 минуты.

5.Клиенты подключается к первому серверу, и запрашивают определенный файл. Если этого файла нет, сервер подключается ко второму серверу и ищет файл там. Если файл найден – он пересылается клиенту, в противном случае клиенту высылается сообщение, что такого файла нет.

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

7.Клиент отсылает строку серверу. Сервер отсылает данную строку на другие сервера, список которых хранится в файле. На этих серверах осуществляется поиск файлов, содержащих данную строку. Результаты поиска отсылаются клиенту.

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

9.Сервер генерирует 3 случайных числа. Если эти числа образуют стороны треугольника, то они передаются клиенту, иначе сервер их просто выводит на экран.

10.Клиент передает файл серверу. Сервер принимает файл и начинает считать буквы алфавита. При каждой сотой обработанной букве передает результат расчета клиенту. Количество обработанных потоков ограничить 4-5.

4.Требования к оформлению отчетов

Титульный лист;

Задание по лабораторной работе;

Граф запуска потоков

Листинг;

Выводы по проделанной работе.

Список литературы

1.Безбогов А.А. Безопасность операционных систем. М.: Гелиос АРВ, 2008. -320 с.

2.Гордеев А.В. Операционные системы. 2-ое издание. С-Пб.: Питер, 2006. -415 с.

3.Таненбаум Э. Современные операционные системы. 2-ое издание. С-Пб.: Питер, 2002. -1037 с.

4.Партыка Т.Л., Попов И.И. Операционные системы, среды и оболочки. М.: Форум, 2010

– 528 с.

5.Столлингс В. Операционные системы. 4-ое издание. Киев: Вильямс, 2010, -848 с.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]