Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Олифер. Сетевые операционные системы.docx
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
16.5 Mб
Скачать

Механизм Sockets ос Unix

Механизм сокетов (sockets) впервые появился в BSD Unix (Berkeley Software Distribution Unix — ветвь Unix, начавшая развиваться в калифорнийском университете Беркли) версии 4.3. Позже он превратился в одну из самых популярных систем сетевого обмена сообщениями. Сегодня этот механизм реализован во многих операционных системах, иногда его по-прежнему называют Berkeley Sockets, отдавая дань уважения его создателям, хотя существует большое количество его реализаций как для различных ОС семейства Unix, так и для других ОС, например для ОС семейства Windows, где он носит название Windows Sockets (WinSock).

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

  • Независимость от нижележащих сетевых протоколов и технологий. Для этого используется понятие коммуникационный домен (communication domain). Коммуникационный домен обладает некоторым набором коммуникационных свойств, определяющих способ именования сетевые узлов и ресурсов, характеристики сетевых соединений (надежные, дейтаграммные, упорядоченные), способы синхронизации процессов и т. п. Одним из наиболее популярных доменов является домен Интернета с протоколами стека TCP/IP.

  • Использование абстрактной конечной точки соединения, получившей название сокета (socket — гнездо). Сокет — это точка, через которую сообщения уходят в сеть или принимаются из сети. Сетевое соединение между двумя процессами осуществляется через пару сокетов. Каждый процесс пользуется своим сокетом, при этом сокеты могут находиться как на разных компьютерах, так и на одном (в этом случае сетевое взаимодействие между процессами сводится к локальному).

  • Сокет может иметь как высокоуровневое символьное имя (адрес), так и низкоуровневое, отражающее специфику адресации определенного коммуникационного домена. Например, в домене Интернета низкоуровневое имя представлено парой IP-адрес, порт.

  • Для каждого коммуникационного домена могут существовать сокеты различных типов. С помощью сокета можно задать определенный вид взаимодействия, имеющий смысл для домена. Так, во многих доменах, помимо дейтаграммных (datagram), существуют потоковые (stream) соединения, гаранти­рующие надежную упорядоченную доставку.

Для обмена сообщениями механизм сокетов предлагает следующие примитивы, реализованные как системные вызовы:

  • Создание сокета:

s = socket(domain, type, protocol)

Процесс должен создать сокет перед началом его использования. Системный вызов socket создает новый сокет с параметрами, определяющими коммуникационный домен (domain), тип соединения, поддерживаемого сокетом (type), и транспортный протокол (например, TCP или UDP), который будет обслуживать это соединение. Если транспортный протокол не задан, то система сама выбирает протокол, соответствующий типу сокета. Указание домена определяет возможные значения остальных двух параметров. Системный вызов socket возвращает дескриптор созданного сокета, который используется как идентификатор сокета в последующих операциях.

  • Связывание сокета с адресом:

bind(s, addг, addrlen)

Системный вызов bind связывает созданный сокет с его высокоуровневым именем или с низкоуровневым адресом. Адрес addr относится к тому узлу, на котором расположен сокет. Для низкоуровневого адреса домена Интернета адресом будет пара IP-адрес, порт. Третий параметр делает адрес независимым от домена, позволяя задавать адреса различных типов, в том числе символьные. Связывать сокет с адресом необходимо только в том случае, если на данный сокет будут приниматься сообщения.

  • Запрос на установление соединения с удаленным сокетом:

connect(s, server_addr. server_addrlrn)

Системный вызов connect используется только в том случае, если предполагается передавать сообщения в потоковом режиме, который требует установления соединения. Процедура установления несимметрична: один процесс (процесс-сервер) ждет запроса на установление соединения, а второй (процесс-клиент) инициирует соединение, посылая такой запрос. Системный вызов connect является запросом клиента на установление соединения с сервером. Второй и третий аргументы вызова указывают адрес сокета сервера, с которым устанавливается соединение. После установления соединения сообщения по нему могут передаваться в дуплексном режиме, то есть в любом направлении. Системный вызов wr i te, используемый для передачи сообщений в рамках установленного соединения, не требует указания адреса сокета получателя, так как локальный сокет, через который сообщение отправляется, уже соединен с определенным удаленным сокетом. Способ, с помощью которого клиенты узнают адрес сокета сервера, не стандартизован.

  • Ожидание запроса на установление соединения:

listen(s, backlog)

Системный вызов listen используется для организации режима ожидания сервером запросов на установление соединения. Система обмена сообщениями после отработки данного системного вызова будет принимать запросы на установление соединения, имеющие адрес сокета s, и передавать их на обработку другому системному вызову — accept, который решает, принимать их или отвергать. Аргумент backlog оговаривает максимальное число хранимых системой запросов на установление соединения, ожидающих принятия.

  • Принятие запроса на установление соединения-.

snew = accept(s, client_addr, Client_addrlen)

Системный вызов accept используется сервером для приема запроса на установление соединения, поступившего от системного вызова listen через сокет s от клиента с адресом client_addr (если этот аргумент опущен, то принимается запрос от любого клиента). При этом создается новый сокет snew, через который и устанавливается соединение с данным клиентом. Таким образом, сокет s используется сервером для приема запросов на установление соединения от клиентов, а сокеты snew — для обмена сообщениями с клиентами по индивидуальным соединениям.

  • Отправка сообщения по установленному соединению:

write(s, message, msg_len)

Сообщение длиной msg_len, хранящееся в буфере message, отправляется получателю, с которым предварительно соединяется сокет s.

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

nbytes =read(snew, buffer, amount)

Сообщение, поступившее через сокет snew, с которым предварительно соединяется отправитель, принимается в буфер buffer размером amount. Если сообщений нет, то процесс-получатель блокируется.

  • Отправка сообщения без установления соединения:

sendto(s, message, receiver_address)

Так как сообщение отправляется без предварительного установления соеди­нения, то в каждом системном вызове send to необходимо указывать адрес сокета получателя.

  • Прием сообщения без установления соединения:

amount = recvfrom(s, message, sender_address)

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

Рассмотрим использование системных вызовов механизма сокетов для организации обмена сообщениями Между двумя узлами.

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

s = socket(AF_INET, SOCK_DGRAM,0); bind(s, sender_addr, sender_addrlen): sendto(s, message, receiver_addr): close(s);

Соответственно, фрагмент программы для процесса-получателя:

s = socket(AF_INET, SOCK_DGRAM,0); bind(s, receiver_addr, receiver_addrlen); amount = recvfrom(s, message, sender_addr); close(s);

Константа AF_INET определяет, что обмен ведется в коммуникационном домене Интернета, а константа SOCK_DGRAM задает дейтаграммный режим обмена без установления соединения. Выбор транспортного протокола оставлен на усмотрение системы.

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

Для процесса-клиента:

s = socket(A£_INET, SOCK_STREAM,в);

connect(s, server_addr, server_addrlen);

write(s, message, msg_len);

write(s, message, msg_len);

close(s);

Для процесса-сервера:

s = socket(AF_INET, SOCK_STREAM,0);

bind(s, server_addr, server_addrlen);

listen(s, backlog);

snew = accept(s, client_addr, client_addrlen);

nbytes = read(snew, buffer, amount);

nbytes = read(snew, buffer, amount);

close(s); N