Составители:
Рубрика:
Привязка порта к сокету
Работа с ТСР-сокетами начинается с вызова функции socket (), которой передается константа
SOCK_STREAM. Но теперь требуется задать также номер порта, чтобы клиент мог к нему подключить-
ся.
Функция bind() спрашивает у операционной системы, может ли программа завладеть портом с
указанным номером. Если сервер не указывает порт, система назначает ему ближайший доступный порт
из
пула номеров. Этот номер может быть разным при каждом следующем запуске программы.
Если программа запрашивает порт, но не получает его, значит, сервер уже выполняется. Опера-
ционная система связывает порт только с одним процессом.
Объявление функции bind() выглядит так:
#include <sys/socket.h>
#include <resolv.h>
int bind(int sd, struct sockaddr *addr, int addr size);
Параметр sd является дескриптором ранее созданного сокета. В параметре addr передается струк-
тура семейства sockaddr. В ней указывается семейство протоколов, адрес сервера и номер порта (см.
выше). Последний параметр содержит размер структуры sockaddr. Его необходимо задавать, потому что
такова концепция библиотеки Socket API: один интерфейс, но много архитектур. Операционная система
поддерживает множество протоколов, у каждого из
которых своя адресная структура.
Перед вызовом функции bind() необходимо заполнить поля структуры sockaddr (Листинг 3).
Листинг 3. Вызов функции bind() в TCP-сервере
/**************************************************************/
/*** Пример ТСР-сокета: заполнение структуры ***/
/*** sockaddr_in ***/
/**************************************************************/
struct sockaddr_in addr; /* создаем ТСР-сокет */
bzero(&addr, sizeof(addr)); /* обнуляем структуру */
addr.sin_family = AF_INET; /* выбираем стек TCP/IP */
addr.sin_port = htons(MY_PORT); /* задаем номер порта */
addr.sin_addr.s_addr = INADDR_ANY; /* любой IP-адрес */
if ( bind(sd, &addr, sizeof(addr)) != 0 ) /* запрашиваем порт */
perror("Bind AF_INET");
В следующем фрагменте программы (Листинг 4) осуществляется инициализация именованного
сокета (семейство AF_UNIX или AF_LOCAL).
Листинг 4.Вызов функции bind() в локальном сервере
У****************************************************************/
/*** Пример локального сокета: заполнение структуры ***/
/*** sockaddr_ux ***/
/****************************************************************/
#include <linux/un.h>
struct sockaddr ux addr; /* создаем локальный именованный сокет */
bzero(&addr, sizeof(addr)); /* обнуляем структуру */
addr.sun family = AF LOCAL; /* выбираем именованные сокеты */
strcpy(addr.sun_path, "/tmp/mysocket"); /* выбираем имя */
if ( bind(sd, saddr, sizeof(addr)) != 0 ) /* привязка к файлу */
perror("Bind AF_LOCAL");
Если запустить на выполнение эту программу, то после ее завершения в каталоге /tmp появится
файл mysocket. Именованные сокеты используются системным демоном регистрации сообщений, sys-
logd, для сбора информации: системные процессы устанавливают соединение с сокетом демона и посы-
лают в него сообщения.
В результате выполнения функции bind() могут возникнуть перечисленные ниже ошибки.
•EBADF. Указан неверный дескриптор сокета. Эта ошибка возникает, если вызов функции socket
() завершился неуспешно, а программа не проверила код ее завершения.
•EACCES. Запрашиваемый номер порта доступен только пользователю root. Помните, что для
доступа к портам с номерами 0—1023 программа должна иметь привилегии пользователя
root. Подробнее об этом рассказывалось в главе 2, "Основы TCP/IP".
•EINVAL. Порт уже
используется. Возможно, им завладела другая программа. Эта ошибка может
также возникнуть, если сервер завис и вы тут же запускаете его повторно. Для операционной
системы требуется время, чтобы освободить занятый порт (до пяти минут!).
Привязка порта к сокету Работа с ТСР-сокетами начинается с вызова функции socket (), которой передается константа SOCK_STREAM. Но теперь требуется задать также номер порта, чтобы клиент мог к нему подключить- ся. Функция bind() спрашивает у операционной системы, может ли программа завладеть портом с указанным номером. Если сервер не указывает порт, система назначает ему ближайший доступный порт из пула номеров. Этот номер может быть разным при каждом следующем запуске программы. Если программа запрашивает порт, но не получает его, значит, сервер уже выполняется. Опера- ционная система связывает порт только с одним процессом. Объявление функции bind() выглядит так: #include#include int bind(int sd, struct sockaddr *addr, int addr size); Параметр sd является дескриптором ранее созданного сокета. В параметре addr передается струк- тура семейства sockaddr. В ней указывается семейство протоколов, адрес сервера и номер порта (см. выше). Последний параметр содержит размер структуры sockaddr. Его необходимо задавать, потому что такова концепция библиотеки Socket API: один интерфейс, но много архитектур. Операционная система поддерживает множество протоколов, у каждого из которых своя адресная структура. Перед вызовом функции bind() необходимо заполнить поля структуры sockaddr (Листинг 3). Листинг 3. Вызов функции bind() в TCP-сервере /**************************************************************/ /*** Пример ТСР-сокета: заполнение структуры ***/ /*** sockaddr_in ***/ /**************************************************************/ struct sockaddr_in addr; /* создаем ТСР-сокет */ bzero(&addr, sizeof(addr)); /* обнуляем структуру */ addr.sin_family = AF_INET; /* выбираем стек TCP/IP */ addr.sin_port = htons(MY_PORT); /* задаем номер порта */ addr.sin_addr.s_addr = INADDR_ANY; /* любой IP-адрес */ if ( bind(sd, &addr, sizeof(addr)) != 0 ) /* запрашиваем порт */ perror("Bind AF_INET"); В следующем фрагменте программы (Листинг 4) осуществляется инициализация именованного сокета (семейство AF_UNIX или AF_LOCAL). Листинг 4.Вызов функции bind() в локальном сервере У****************************************************************/ /*** Пример локального сокета: заполнение структуры ***/ /*** sockaddr_ux ***/ /****************************************************************/ #include struct sockaddr ux addr; /* создаем локальный именованный сокет */ bzero(&addr, sizeof(addr)); /* обнуляем структуру */ addr.sun family = AF LOCAL; /* выбираем именованные сокеты */ strcpy(addr.sun_path, "/tmp/mysocket"); /* выбираем имя */ if ( bind(sd, saddr, sizeof(addr)) != 0 ) /* привязка к файлу */ perror("Bind AF_LOCAL"); Если запустить на выполнение эту программу, то после ее завершения в каталоге /tmp появится файл mysocket. Именованные сокеты используются системным демоном регистрации сообщений, sys- logd, для сбора информации: системные процессы устанавливают соединение с сокетом демона и посы- лают в него сообщения. В результате выполнения функции bind() могут возникнуть перечисленные ниже ошибки. •EBADF. Указан неверный дескриптор сокета. Эта ошибка возникает, если вызов функции socket () завершился неуспешно, а программа не проверила код ее завершения. •EACCES. Запрашиваемый номер порта доступен только пользователю root. Помните, что для доступа к портам с номерами 0—1023 программа должна иметь привилегии пользователя root. Подробнее об этом рассказывалось в главе 2, "Основы TCP/IP". •EINVAL. Порт уже используется. Возможно, им завладела другая программа. Эта ошибка может также возникнуть, если сервер завис и вы тут же запускаете его повторно. Для операционной системы требуется время, чтобы освободить занятый порт (до пяти минут!).
Страницы
- « первая
- ‹ предыдущая
- …
- 12
- 13
- 14
- 15
- 16
- …
- следующая ›
- последняя »