Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СистПриклПрогЗабез(Хихловская).doc
Скачиваний:
25
Добавлен:
10.02.2016
Размер:
961.02 Кб
Скачать

Програмныйинтерфейс сокетов

Сокет – это коммуникационный интерфейс взаимодействующих процессов, конкретный вид взаимодействия зависит от коммуникационного домена, в рамках которого создан сокет.

Название сокета тип сокета

Sock_dgram сокет датограмм

Sock_stream сокет потока

Sock_seqpacket сокет пакетов

Sock_rav сокет нужного уровня

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

Для создания сокета используются системный вызов socket(2);

#include <sys/type.h>

#include <sys/. socket h>

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

domain - домен

type – тип сокета

protocol – используемуй протокол

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

AF_UNIX—Домен локального межпроцессного взаимодействия в пределах единой системы процессов

AF_INET—Домен взаимодействия систем. протокол TCP/IP

AF_NS—Протоколы XEROX NS

Домен и семейство протоколов определяет адресное пространство взаимодействия, потому в названиях присутствует AF—AddressFamily—ceмейство адрасов. Допустимо также PF_UNIX,PF_INET—семейство протоколов.

Поддержка различных типов сокетов в доменах

домен

AF_UNIX

AF_INET

Тип сокета

SOCK_STREAM

Да

Да

SOCK_DGRAM

Да

Да

SOCK_SEQPACKER

Нет

Нет

SOCK_RAW

Нет

Нет

Для домена AF_INET возможны комбинации

Сокет Протокол

SOCK_STREAM IPPROTO_TCP(TCP)

SOCK_DGRAM IPPROTO_UDR(UDR)

SOCK_RAW IPPROTO_ICMP(ICMP)

SOCK_RAW IPPROTO_RAW(IP)

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

  1. Коммуникационным протоколом

  2. Локальным адресом

  3. Локальным

  4. Удаленным адресом

  5. Удаленным процессом

Адрес определяет ОС (или хост сети), а процесс – конкретное приложение, получающее или передающее данные. Конкретные значения и формат этих параметров определяются коммуникационным доменом.

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

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

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

На обоих рисунках показано, что фактической передаче данных предшествует начальная фаза связанная (binding) сокета, когда устанавливается дополнительная информация, необходимая для определения коммуникационного узла. Это реализуется с помощью системного вызова bind(2)

#include <sys/type.h>

#include <sys/socket.h>

int bind (int sockfd,struct sockaddr *localaddr,int addrlen);

Здесь socket – дескриптор сокета, полученный при его создании ;аргумент *localaddr определяет локальный адрес, с которым необходимо связать сокет; параметр addrlen определяет размер адреса. Связывание с локальным адресом, который определяет два параметра коммуникационного канала (коммуникационный узел): локальный адрес и локальный процесс.

Адрес сокета зависит от коммуникационного домена, в рамках которого он определен, в файле <sys/socket.h> struct sockaddr {

U_short;

Char sa_data [14];

};

Поле sa_family определяет коммуникационный домен (семейство протоколов), а sa_data – содержит собственно адрес, формат которого определен для каждого домена. Для внутреннего домена UNIX адрес выглядит так: определен в <sys/un.h>;

Struct sockaddr_un {

Short sun_family; /*= = AF_UNIX*/

Char sun_path [108];

};

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

Для сетевого обмена данными необходимо указание локального процесса и хоста, на котором выполняется этот процесс. Для семейства протоколов TCP/IP определен формат адреса в файле <netinet/in.hr>;

Struct sockakddr_in {

Short sin_family; /*= = AF_INET*/

U_short sin port;

Struct in addr sin_addr;

Char sin_zero[8];

};

Это IP-адрес хоста—32-разрядного число целое sin_addr, а процесс (приложение) адресуется 16-разрядным номером порта sin_port.

UNIX ДОМЕН INTERNET ДОМЕН

Адреса сокетов

Связывание необходимо для присвоения сокету ложного адреса и определения коммуникационного узла. В трех случаях для этой цели используется функция bind (2):

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

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

  3. Даже в случае взаимодействия с использованием виртуального канала клиент может при желании зарегистрировать свой адрес, не полагаясь при этом на систему

Назначение адреса для клиента можно выполнить также с помощью системного вызова connect(2), устанавливающего сокет клиента с локальным коммуникационным узлом. Вызов connect(2) имеет вид:

#include <sys/type.h>

# include <sys/socket.h>

int connect (int.socket, struct sockaddr *servaddr,int addrlen);

вызов предполагает создание виртуального канала и используется для предварительного установления связи между коммуникационными узлами. В этом случае клиенту нет необходимости явно связывать сокет с помощью системного вызова bind (2). Локальный узел коммуникационного канала указывает дескриптором сокета socket, для которого система автоматически выбирает приемлемые значения локального адреса и процесса. Удаленный узел определяется аргументом servadder, который указывает на адрес сервера, addrlen задает его длину.

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

Системный вызов listen(2) информирует систему, что сервер готов принимать запросы. Он имеет следующий вид:

#include <sys/types.h>

#include <sys/socket.h>

int listen (int sockfd, int backlog);

Параметр sockfd определяет сокет, который будет использоваться для получения запросов в предположении, что сокет был предварительно связан с известным адресом, т.е. предварительно создал виртуальный канал между сервером и каналом. Параметр backlog указывает максимальное число запросов на установление связи, которые могут ожидать обработки сервером.

Фактическую обработку запроса клиента на установление связи производит системный вызов assept (2)

#include <sys/types.h>

#include <sys/socket.h>

int assept (int sockfd,struct sockaddr *clntaddr, int *addrlen);

вызов assept (2)извлекает первый запрос из очереди и создает новый сокет, характеристики которого не отличаются от сокета sockfd, и таким образом завершает создание виртуального канала со стороны сервера. Одновременно assept (2) возвращает параметры удаленного коммуникационного узла – адрес клиента elntaddr и его размер addrlen. Новый сокет используется для обслуживания созданного виртуального канала, а полученный адрес клиента не помогает анонимность клиента. Типичный сценарий.

Sockfd = Socket (…) создать сокет

Bind (sockfd,…); связать его с известным локальным адресом

Listen (sockfd,…); организовать очередь запросов

For ( ; ;) {

Newsockfd – accept (sockfd,…); померить запрос

If (fork () = = 0 { породить дочерний процесс

Close (sockfd); дочерний процесс

exit (0);

}

else

close (newsockfd); родительский процесс

}

В это время как дочерний процесс обеспечивает фактически обмен данными с клиентом, родительский процесс продолжает “прослушивать” запросы клиентов, порождая для них отдельные процессы – обработки, очередь позволяет буферезировать запросы на время, пока сервер завершает вызов assept (2) и затем создает дочерний процесс. Новый соке newsockfd, полученный в результате вызова assept(2), адресует полностью определенный коммуникационный канал: протоколы и полные адреса обоих узлов – клиента и сервера. Для сокета sockfd определена только локальная часть канала. Это позволяет серверу продолжать использовать sockfd для “прослушивания последующих запросов”.

Если для сокетов потока на приема и передаче данных могут быть использованы стандартные вызовы read (2) и write (2), то сокеты датограмм должны пользоваться специальными системными функциями: send(2),которые используются для передачи данных удаленному узлу, а фунуции иrecvfrom(2) – для их приема. Отличие между ними заключается в том, чтоsend(2) иrecv(2) используются только для подсоединения сокета после вызоваconnect(2). Все эти вызовы используются в качестве первого аргумента дескриптор сокета, через который производится обмен данными. Аргументmsgсодержит сообщение длинойlen,которое должно быть передано по адресуToaddr, длина которого составляетTolenбайтов. Для функцииGend(2) используется адрес получателя, установленный предшествующим вызовомConnect(2). Аргумент вид представляет собой буфер, в котором копируются полученные данные

Параметр flagsможет принимать следующее назначение:

MSG_OOBпередать или принять экстренные данные (out-of-band) вместо обычных

MSG_PEEKпросмотреть данные, не удаляя их из системного буфера

#include <sys/tpes.h>

#include <sys/socket.h>

int send (int s,const char*msg, int len, int flags);

int send to (int s, const char*msg, int len, int flags, const struct sockaddr*toaddr, int tolen);

int recv (int s, shar*bul, int len, int flags);

int recvfrom (int s, char*bul, int len, int flags, struct sockaddr*fromaddr, int*fromlen);