11.13. Функция tcp_listen

11.13. Функция tcp_listen

Наша следующая функция, tcp_listen, выполняет обычные шаги сервера TCP: создание сокета TCP, связывание его с заранее известным портом с помощью функции bind и разрешение приема входящих запросов через соединение. В листинге 11.6 представлен исходный код.

#include "unp.h"

int tcp_listen(const char *hostname, const char *service, socklen_t *lenptr);

В случае успешного выполнения возвращает дескриптор присоединенного сокета, в случае ошибки не возвращает ничего

Листинг 11.6. Функция tcp_listen: выполнение обычных шагов сервера TCP

//lib/tcp_listen.c

 1 #include "unp.h"

 2 int

 3 tcp_listen(const char *host, const char *serv, socklen_t *addrlenp)

 4 {

 5  int listenfd, n;

 6  const int on = 1;

 7  struct addrinfo hints, *res, *ressave;

 8  bzero(&hints, sizeof(struct addrinfo));

 9  hints.ai_flags = AI_PASSIVE;

10  hints.ai_family = AF_UNSPEC;

11  hints.ai_socktype = SOCK_STREAM;

12  if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)

13   err_quit("tcp_listen error for %s, %s: %s",

14    host, serv, gai_strerror(n));

15  ressave = res;

16  do {

17   listenfd =

18    socket(res->ai_family, res->ai_socktype, res->ai_protocol);

19   if (listenfd < 0)

20    continue; /* ошибка, пробуем следующий адрес */

21   Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

22   if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)

23    break; /* успех */

24   Close(listenfd); /* ошибка при вызове функции bind, закрываем

                         сокет и пробуем следующий адрес*/

25  } while ((res = res->ai_next) != NULL);

26  if (res == NULL) /* значение errno устанавливается при последнем

                        вызове функции socket() или bind() */

27   err_sys("tcp_listen error for %s, %s", host, serv);

28  Listen(listenfd, LISTENQ);

29  if (addrlenp)

30   *addrlenp = res->ai_addrlen; /* возвращает размер адреса протокола */

31  freeaddrinfo(ressave);

32  return (listenfd);

33 }

Вызов функции getaddrinfo

8-15 Мы инициализируем структуру addrinfo с учетом следующих рекомендаций (элементов структуры hints): AI_PASSIVE, поскольку это функция для сервера, AF_UNSPEC для семейства адресов и SOCK_STREAM. Вспомните табл. 11.3: если имя узла не задано (что вполне нормально для сервера, который хочет связать с дескриптором универсальный адрес), то наличие значений AI_PASSIVE и AF_UNSPEC вызовет возвращение двух структур адреса сокета: первой для IPv6 и второй для IPv4 (в предположении, что это узел с двойным стеком).

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

16-24 Вызываются функции socket и bind. Если любой из вызовов окажется неудачным, мы просто игнорируем данную структуру addrinfo и переходим к следующей. Как было сказано в разделе 7.5, для сервера TCP мы всегда устанавливаем параметр сокета SO_REUSEADDR.

Проверка на наличие ошибки

25-26 Если все вызовы функций socket и bind окажутся неудачными, мы сообщаем об ошибке и завершаем выполнение. Как и в случае с нашей функцией tcp_connect из предыдущего раздела, мы не пытаемся возвратить ошибку из этой функции.

27 Сокет превращается в прослушиваемый сокет с помощью функции listen.

Возвращение размера структуры адреса

28-31 Если аргумент addrlenp является непустым указателем, мы возвращаем размер адресов протокола через этот указатель. Это позволяет вызывающему процессу выделять память для структуры адреса сокета, чтобы получить адрес протокола клиента из функции accept (см. также упражнение 11.7).

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Функция SUM

Из книги Обработка баз данных на Visual Basic®.NET автора Мак-Манус Джеффри П

Функция SUM Ваши возможности в подведении итогов не ограничены простым подсчетом записей. Используя функцию SUM, можно генерировать итоговые результаты для всех возвращаемых записей по любым числовым полям. Например, для создания запроса, который генерирует итоги по


Функция uni()

Из книги Fiction Book Designer Краткое руководство автора Автор неизвестен

Функция uni() Поиск/замена символа по его юникодному номеру также может быть сделана при помощи функции uni().Пример функции uni(): Boouni(107,32)Designer найдет слово Book


Функция uni()

Из книги Fiction Book Designer 3.2. Краткое руководство автора Izekbis

Функция uni() Поиск/замена символа по его юникодному номеру также может быть сделана при помощи функции uni().Пример функции uni(): Boouni(107,32)Designer найдет слово Book


Функция pthread_rwlock_wrlock

Из книги UNIX: взаимодействие процессов автора Стивенс Уильям Ричард

Функция pthread_rwlock_wrlock Текст функции pthread_rwlock_wrlock приведен в листинге 8.6.11-17 Если ресурс заблокирован на считывание или запись (значение rw_refcount отлично от 0), мы приостанавливаем выполнение потока. Для этого мы увеличиваем rw_nwaitwriters и вызываем pthread_cond_wait с условной переменной


Функция pthread_rwlock_trywrlock

Из книги Технология XSLT автора Валиков Алексей Николаевич

Функция pthread_rwlock_trywrlock Неблокируемая функция pthread_rwlock_trywrlock показана в листинге 8.7.11-14 Если значение счетчика rw_refcount отлично от нуля, блокировка в данный момент уже установлена считывающим или записывающим процессом (это безразлично) и мы возвращаем ошибку с кодом EBUSY. В


Функция pthread_rwlock_unlock

Из книги PGP: Кодирование и шифрование информации с открытым ключом. автора Левин Максим

Функция pthread_rwlock_unlock Последняя функция, pthread_rwlock_unlock, приведена в листинге 8.8.Листинг 8.8. Функция pthread_rwlock_unlock: разблокирование ресурса//my_rwlock/pthread_rwlock_unlock.c1  #include "unpipc.h"2  #include "pthread_rwlock.h"3  int4  pthread_rwlock_unlock(pthread_rwlock_t *rw)5  {6   int result;7   if (rw->rw_magic != RW_MAGIC)8    return(EINVAL);9   if ((result =


Функция sem_open

Из книги Fiction Book Designer 3.2. Руководство по созданию книг автора

Функция sem_open В листинге 10.37 приведен текст первой половины функции sem_open, которая создает новый семафор или открывает существующий.Листинг 10.37. Функция sem_open: первая часть//my_pxsem_svsem/sem_open. с1  #include "unpipc.h"2  #include "semaphore.h"3  #include <stdarg.h> /* для списков аргументов переменной длины


Функция sem_post

Из книги Введение в криптографию автора Циммерманн Филипп

Функция sem_post В листинге 10.41 приведен текст функции sem_post, которая увеличивает значение семафора.11-16 Мы вызываем semop с операцией, увеличивающей значение семафора на 1.Листинг 10.41. Функция sem_post//my_pxsem_svsem/sem_post.с1  #include "unpipc.h"2  #include "semaphore.h"3  int4  mysem_post(mysem_t *sem)5  {6   struct sembuf


Хэш-функция.

Из книги автора

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


Функция uni()

Из книги автора

Функция uni() Поиск/замена символа по его юникодному номеру также может быть сделана при помощи функции uni().Пример функции uni(): Boouni(107,32)Designer найдет слово Book


Хэш-функция

Из книги автора

Хэш-функция Однако описанная выше схема имеет ряд существенных недостатков. Она крайне медлительна и производит слишком большой объём данных — по меньшей мере вдвое больше объёма исходной информации. Улучшением такой схемы становится введение в процесс преобразования