Программирование POSIX сокет. Сукиязов С.А. - 15 стр.

UptoLike

Составители: 

Функция bind() пытается зарезервировать для серверного сокета указанное имя файла или порт
(список доступных или стандартных портов содержится в файле /etc/services). Клиенты подключаются к
данному порту, посылая и принимая через него данные.
Создание очереди ожидания
Сокет обеспечивает интерфейс, посредством которого одна программа может взаимодействовать
с другой по сети. Соединение является эксклюзивным: после того как программа подключилась к порту,
никакая другая программа не может к нему обратиться. Для разрешения подобной ситуации на сервере
создается очередь ожидания.
Очередь сокета активизируется при вызове функции listen (). Когда сервер вызывает эту функ
-
цию, он указывает число позиций в очереди. Кроме того, сокет переводится в режим "только прослуши-
вание". Это очень важно, так как позволяет впоследствии вызывать функцию accept ().
#include <sys/socket.h>
#include <resolv.h>
int listen(int sd, int numslots);
Параметр sd является дескриптором сокета, полученным в результате вызова функции socket ().
Параметр numslots задает число позиций в очереди ожидания. Приведем пример (Листинг 5).
Листинг 5. Пример функции listen ()
/****************************************************************/
/*** Пример функции listen(): перевод сокета ***/
/*** в режим прослушивания клиентских подключений ***/
/****************************************************************/
int sd;
sd = socket(PF_INET, SOCK_STREAM, 0);
/*** Привязка к порту ***/
if ( listen(sd, 20) != 0 ) /* перевод сокета в режим */
perror("Listen"); /* прослушивания очереди с 20-ю позициями */
Как правило, размер очереди устанавливается равным от 5 до 20. Больший размер оказывается
избыточным в современной многозадачной среде. Если многозадачный режим не поддерживается, мо-
жет потребоваться увеличить размер очереди до величины периода тайм-аута (например, 60, если тайм-
аут составляет 60 секунд).
Функция listen () может генерировать следующие ошибки.
1.EBADF. Указан неверный дескриптор сокета.
2.EOPNOTSUPP. Протокол сокета
не поддерживает функцию listen (). В TCP (SOCK_STREAM)
очередь ожидания поддерживается, а в протоколе UDP (SOCK_DGRAM) — нет.
После перевода сокета в режим ожидания необходимо организовать цикл получения запросов на
подключение.
Прием запросов от клиентов
На данный момент программа создала сокет, назначила ему номер порта и организовала очередь
ожидания. Теперь она может принимать запросы на подключение. Функция accept() делает указанный
сокет диспетчером соединений. Здесь привычный ход событий нарушается. Когда сокет переводится в
режим прослушивания, он перестает быть двунаправленным каналом передачи данных. Профамма не
может даже читать данные
из него. Она может только принимать запросы на подключение. Функция
accept () блокирует программу до тех пор, пока не поступит такой запрос.
Когда клиент устанавливает соединение с сервером, сокет, находящийся в режиме прослушива-
ния, организует новый двунаправленный канал между клиентом и своим собственным портом. Функция
accept() неявно создает в программе новый дескриптор
сокета. По сути, при каждом новом подключении
создается выделенный канал между клиентом и сервером. С этого момента программа взаимодействует
с клиентом через новый канал.
Можно также узнать, кто устанавливает соединение с сервером, поскольку в функцию accept()
передается информация о клиенте. Аналогичный процесс рассматривался в главе 4, "Передача сообще-
ний между одноранговыми компьютерами", когда
функция recvfrom() получала не только данные, но и
указатель на адрес отправителя.
#include <sys/socket.h>
#include <resolv.h>
int accept(int sd, sockaddr *addr, int *addr size);
Как всегда, параметр sd является дескриптором сокета. Во втором параметре возвращается адрес
клиента и номер порта, а в третьемразмер структуры sockaddr. В отличие от функции recvfrom(), по-
      Функция bind() пытается зарезервировать для серверного сокета указанное имя файла или порт
(список доступных или стандартных портов содержится в файле /etc/services). Клиенты подключаются к
данному порту, посылая и принимая через него данные.

      Создание очереди ожидания
      Сокет обеспечивает интерфейс, посредством которого одна программа может взаимодействовать
с другой по сети. Соединение является эксклюзивным: после того как программа подключилась к порту,
никакая другая программа не может к нему обратиться. Для разрешения подобной ситуации на сервере
создается очередь ожидания.
      Очередь сокета активизируется при вызове функции listen (). Когда сервер вызывает эту функ-
цию, он указывает число позиций в очереди. Кроме того, сокет переводится в режим "только прослуши-
вание". Это очень важно, так как позволяет впоследствии вызывать функцию accept ().
#include 
#include 
int listen(int sd, int numslots);
     Параметр sd является дескриптором сокета, полученным в результате вызова функции socket ().
Параметр numslots задает число позиций в очереди ожидания. Приведем пример (Листинг 5).
Листинг 5. Пример функции listen ()
/****************************************************************/
/***    Пример функции listen(): перевод сокета                ***/
/***    в режим прослушивания клиентских подключений           ***/
/****************************************************************/
int sd;
sd = socket(PF_INET, SOCK_STREAM, 0);
/*** Привязка к порту ***/
if ( listen(sd, 20) != 0 )             /* перевод сокета в режим */
  perror("Listen");    /* прослушивания очереди с 20-ю позициями */
       Как правило, размер очереди устанавливается равным от 5 до 20. Больший размер оказывается
избыточным в современной многозадачной среде. Если многозадачный режим не поддерживается, мо-
жет потребоваться увеличить размер очереди до величины периода тайм-аута (например, 60, если тайм-
аут составляет 60 секунд).
      Функция listen () может генерировать следующие ошибки.
      1.EBADF. Указан неверный дескриптор сокета.
      2.EOPNOTSUPP. Протокол сокета не поддерживает функцию listen (). В TCP (SOCK_STREAM)
          очередь ожидания поддерживается, а в протоколе UDP (SOCK_DGRAM) — нет.
     После перевода сокета в режим ожидания необходимо организовать цикл получения запросов на
подключение.

      Прием запросов от клиентов
       На данный момент программа создала сокет, назначила ему номер порта и организовала очередь
ожидания. Теперь она может принимать запросы на подключение. Функция accept() делает указанный
сокет диспетчером соединений. Здесь привычный ход событий нарушается. Когда сокет переводится в
режим прослушивания, он перестает быть двунаправленным каналом передачи данных. Профамма не
может даже читать данные из него. Она может только принимать запросы на подключение. Функция
accept () блокирует программу до тех пор, пока не поступит такой запрос.
       Когда клиент устанавливает соединение с сервером, сокет, находящийся в режиме прослушива-
ния, организует новый двунаправленный канал между клиентом и своим собственным портом. Функция
accept() неявно создает в программе новый дескриптор сокета. По сути, при каждом новом подключении
создается выделенный канал между клиентом и сервером. С этого момента программа взаимодействует
с клиентом через новый канал.
      Можно также узнать, кто устанавливает соединение с сервером, поскольку в функцию accept()
передается информация о клиенте. Аналогичный процесс рассматривался в главе 4, "Передача сообще-
ний между одноранговыми компьютерами", когда функция recvfrom() получала не только данные, но и
указатель на адрес отправителя.
#include 
#include 
int accept(int sd, sockaddr *addr, int *addr size);
      Как всегда, параметр sd является дескриптором сокета. Во втором параметре возвращается адрес
клиента и номер порта, а в третьем — размер структуры sockaddr. В отличие от функции recvfrom(), по-