Вход/Регистрация
Операционная система UNIX
вернуться

Робачевский Андрей Михайлович

Шрифт:

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

#include <sys/types.h>

#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *clntaddr,

 int* addrlen);

Вызов accept(2) извлекает первый запрос из очереди и создает новый сокет, характеристики которого не отличаются от сокета

sockfd
, и таким образом завершает создание виртуального канала со стороны сервера. Одновременно accept(2) возвращает параметры удаленного коммуникационного узла — адрес клиента
clntaddr
и его размер
addrlen
. Новый сокет используется для обслуживания созданного виртуального канала, а полученный адрес клиента исключает анонимность последнего. Дальнейший типичный сценарий взаимодействия имеет вид:

sockfd = socket(...);
 Создать сокет

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

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

for(;;) {

 newsockfd = accept(sockfd, ...);
Получить запрос

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

close(sockfd);
 Дочерний процесс

...

exit(0);

 } else

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

}

В этом сценарии, в то время как дочерний процесс обеспечивает фактический обмен данными с клиентом, родительский процесс продолжает "прослушивать" поступающие запросы, порождая для каждого из них отдельный процесс-обработчик. Очередь позволяет буферизовать запросы на время, пока сервер завершает вызов accept(2) и затем создает дочерний процесс. Заметим, что новый сокет

newsockfd
, полученный в результате вызова accept(2), адресует полностью определенный коммуникационный канал: протокол и полные адреса обоих узлов — клиента и сервера. Напротив, для сокета
sockfd
определена только локальная часть канала. Это позволяет серверу продолжать использовать
sockfd
для "прослушивания" последующих запросов.

Наконец, если для сокетов потока при приеме и передаче данных могут быть использованы стандартные вызовы read(2) и write(2), то сокеты дата- грамм должны пользоваться специальными системными вызовами (эти вызовы также доступны для сокетов других типов):

#include <sys/types.h>

#include <sys/socket.h>

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

int sendto(int s, const char *msg, int len, int flags,

 const struct sockaddr* toaddr, int tolen);

int recv(int s, char *buf, int len, int flags);

int recvfrom(int s, char *buf, int len, int flags,

 struct sockaddr* fromaddr, int* fromlen);

Функции send(2) и sendto(2) используются для передачи данных удаленному узлу, а функции recv(2) и recvfrom(2) — для их приема. Основным различием между ними является то, что функции send(2) и recv(2) могут быть использованы только для "подсоединенного" сокета, т.е. после вызова connect(2).

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

msg
содержит сообщение длиной
len
, которое должно быть передано по адресу
toaddr
, длина которого составляет
tolen
байтов. Для функции send(2) используется адрес получателя, установленный предшествовавшим вызовом connect(2). Аргумент
buf
представляет собой буфер, в который копируются полученные данные.

Параметр

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

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

Пример использования сокетов

В заключение приведем пример использования сокетов для организации межпроцессного взаимодействия. Поскольку в данном разделе не затрагиваются сетевые вопросы, то и сокеты, которые будут использованы в примере, принадлежат домену UNIX. Как и в предыдущих примерах, функциональность нашей распределенной системы не отличается разнообразием: клиент посылает серверу сообщение "Здравствуй, Мир!", а сервер отправляет его обратно клиенту, который после получения выводит сообщение на экран.

В примере использованы сокеты датаграмм, которые в домене UNIX практически не отличаются от сокетов потока. В качестве адреса сервера предлагается имя файла ./echo.server (мы полагаем, что в системе запущен только один сервер из данного каталога). Предполагается, что клиенты заранее знают этот адрес. Сервер связывает созданный сокет с этим локальным адресом и таким образом регистрируется в системе. Начиная с этого момента он готов к получению и обработке сообщений. Сервер начинает бесконечный цикл, ожидая сообщений от клиентов, блокируясь на вызове recvfrom(2). При получении сообщения сервер отправляет его обратно, вызывая sendto(2).

  • Читать дальше
  • 1
  • ...
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: