Адреса сокетов. Настройка адреса сокета. Системный вызов bind()

Когда сокет создан, необходимо настроить его адрес. Для этого используется системный вызов bind(). Первый параметр вызова должен содержать дескриптор сокета, для которого производится настройка адреса. Второй и третий параметры задают этот адрес.

Во втором параметре должен быть указатель на структуру struct sockaddr, содержащую удаленную и локальные части полного адреса.

Указатели типа struct sockaddr * встречаются во многих сетевых системных вызовах; они используются для передачи информации о том, к какому адресу привязан или должен быть привязан сокет. Рассмотрим этот тип данных подробнее. Структура struct sockaddr описана в файле <sys/socket.h> следующим образом:

struct sockaddr {

short sa_family;

char sa_data[14];

};

Для работы с семейством протоколов TCP/IP мы будем использовать адрес сокета следующего вида, описанного в файле <netinet/in.h>:

struct sockaddr _in{

short sin_family;

/* Избранное семейство протоколов

– всегда AF_INET */

unsigned short sin_port;

/* 16-битовый номер порта в сетевом

порядке байт */

struct in_addr sin_addr;

/* Адрес сетевого интерфейса */

char sin_zero[8];

/* Это поле не используется, но должно

всегда быть заполнено нулями */

};

Первый элемент структуры – sin_family задает семейство протоколов. В него мы будем заносить уже известную нам предопределенную константу AF_INET (см. предыдущий раздел).

Удаленная часть полного адреса – IP-адрес – содержится в структуре типа struct in_addr, с которой мы встречались в разделе "Функции преобразования IP-адресов inet_ntoa(),inet_aton()".

Для указания номера порта предназначен элемент структуры sin_port, в котором номер порта должен храниться в сетевом порядке байт. Существует два варианта задания номерапорта: фиксированный порт по желанию пользователя и порт, который произвольно назначает операционная система. Первый вариант требует указания в качестве номера портаположительного заранее известного числа и для протокола UDP обычно используется при настройке адресов сокетов и при передаче информации с помощью системного вызова sendto()(см. следующий раздел). Второй вариант требует указания в качестве номера порта значения 0. В этом случае операционная система сама привязывает сокет к свободному номеру порта. Этот способ обычно используется при настройке сокетов программ клиентов, когда заранее точно знать номер порта для программисту необязательно.

IP–адрес при настройке также может быть определен двумя способами. Он может быть привязан к конкретному сетевому интерфейсу (т.е. сетевой плате), заставляя операционную систему принимать/передавать информацию только через этот сетевой интерфейс, а может быть привязан и ко всей вычислительной системе в целом (информация может быть получена/отослана через любой сетевой интерфейс). В первом случае в качестве значения поля структуры sin_addr.s_addr используется числовое значение IP-адреса конкретного сетевого интерфейса в сетевом порядке байт. Во втором случае это значение должно быть равно значению предопределенной константы INADDR_ANY, приведенному к сетевому порядку байт.

Третий параметр системного вызова bind() должен содержать фактическую длину структуры, адрес которой передается в качестве второго параметра. Эта длина меняется в зависимости от семейства протоколов и даже различается в пределах одного семейства протоколов. Размер структуры, содержащей адрес сокета, для семейства протоколов TCP/IP может быть определен как sizeof(struct sockaddr_in).

Системный вызов для привязки сокета к конкретному адресу Прототип системного вызова #include <sys/types.h> #include <sys/socket.h> int bind(int sockd, struct sockaddr *my_addr, int addrlen); Описание системного вызова Системный вызов bind служит для привязки созданного сокета к определенному полному адресу вычислительной сети. Параметр sockd является дескриптором созданного ранее коммуникационного узла, т. е. значением, которое вернул системный вызов socket(). Параметр my_addr представляет собой адрес структуры, содержащей информацию о том, куда именно мы хотим привязать наш сокет – то, что принято называть адресом сокета. Он имеет тип указателя на структуру-шаблон struct sockaddr, которая должна быть конкретизирована в зависимости от используемого семейства протоколов и заполнена перед вызовом. Параметр addrlen должен содержать фактическую длину структуры, адрес которой передается в качестве второго параметра. Эта длина в разных семействах протоколов и даже в пределах одного семейства протоколов может быть различной (например, для UNIX Domain). Возвращаемое значение Системный вызов возвращает значение 0 при нормальном завершении и отрицательное значение – в случае ошибки. 40. Создание сокетов и адресации для IPX/ SPX Адресация В IPX-сетях сегменты соединяются через IPX-маршрутизаторы. Каждому сег-менту назначается уникальный четырехбайтный номер сети (network num-ber). Эти номера используются IPX-маршрутизатами для управления подклю-чениями между разными сегментами сети. Компьютер, подключенный к сег-менту сети, идентифицируется при помощи шестибайтного номера узла (node number) — обычно это физический адрес сетевого адаптера. Узел (компьютер) вправе запускать несколько процессов связи по IPX, для разли-чения которых применяются номера сокетов Для подготовки Winsock-клиента или сервера к подключению по IPX, необходимо настроить структуру SOCKADDRJPX Она определена в заголо-вочном файле Wsipx h, ссылка на него в приложении должна идти вслед за Winsock2 h Структура SOCKADDRJPX определена так typedef struct sockaddr_ipx { short sa_family, char sa_netnum[4], char sa_nodenum[6], unsigned short sa_socket, } SOCKADDR_IPX, *PSOCKADDR_IPX, FAR *LPSOCKADDR_IPX, Поле sajamily всегда равно AF_IPX Поле sajnetnum — 4-байтный номер сети в сегменте IPX-сети Поле sajiodenum — б-байтный номер узла Поле sa_socket представляет сокет или порт, используемый для различения IPX-подключений на одном узле. Создание сокета Создать IPX-сокет можно несколькими способами Для открытия 1РХ-соке-та вызовите функции socket или WSASocket с семейством адресов AFJPX, ти-пом сокета SOCKJDGRAM и протоколом NSPROTOJPX s = socket(AF_IPX, SOCK.DGRAM, NSPROTO.IPX), s = WSASocket(AF_IPX, SOCK.DGRAM, NSPROTO_IPX, NULL, 0, WSA_FLAG_OVERLAPPED), Заметьте, что третий параметр протокола должен быть обязательно задан и не равен 0 Это важно, поскольку поле протокола может использоваться для настройки особых типов IPX-пакетов. Как мы уже говорили, IPX обеспечивает ненадежное соединение без дей-таграмм Если приложению требуется надежное соединение с применени-ем этого протокола, оно может использовать поверх IPX протоколы более высокого уровня, такие как SPX и SPX II Для этого необходимо при вызове функций socket или WSASocket задать соответствующие значения полей типа — SOCK_SEQPACKET или SOCKJTREAM, и протокола — NSPROTO_SPX или NSPROTOJPXII Если тип сокета — SOCKJSTREAM, данные передаются в виде непрерывно-го потока байт, без разделения сообщений, подобно действию сокета в TCP/IP Если тип сокета — SOCK_SEQPACKET, данные передаются с разделителя-ми сообщений Например, передатчик отправляет 2000 байт — приемник не сможет ответить, пока не получит все 2000 байт В SPX и SPXII для этого нуж-но указать бит конца сообщения в заголовке SPX Для сокетов типа SOCK_SEQPACKET подразумевается, что этот бит указан, и выполнение Winsock-функции recv и WSARecv не завершится, пока пакет не будет получен Для поточных сокетов бит конца сообщения не требуется, и выполнение функ-ции recv будет завершено сразу же по получении любых данных, независимо от наличия бита конца сообщения С точки зрения отправителя при ис-пользовании типа SOCK_SEQPACKET сообщения размером меньше пакета, всегда передаются с указанным битом конца При отправке нескольких па-кетов этот бит задается только в последнем пакете Привязка сокета Когда IPX-приложение при помощи функции bind создаст привязку локаль-ного адреса к сокету, указывать номер сети и адрес узла в структуре SOCKA-DDR IPX не нужно Функция bind заполнит эти поля при помощи первого же сетевого интерфейса IPX, доступного в системе Если на компьютере ус-тановлено несколько сетевых адаптеров, привязка к конкретному интерфей-су также не требуется В Windows 95, Windows 98, Windows NT и Windows 2000 реализована виртуальная внутренняя сеть, в которой к каждому сете вому адаптеру можно обратиться, независимо от того, к какой физической сети он подключен (Внутренние номера сети подробно рассмотрены далее в этой главе) После успешной привязки приложения к локальному интер-фейсу с помощью функции getsockname вы можете узнать номер локальной сети и номер узла следующим образом SOCKET sdServer, SOCKADOR.IPX IPXAddr, int addrlen = sizeof(SOCKADDR_IPX), if ((sdServer = socket (AF_IPX, SOCK_DGRAM, NSPROTO.IPX)) == INVALID_SOCKET) { printf(socket failed with error Xd\n, WSAGetLastErrorO), return, ZeroMemory(&IPXAddr, sizeof(SOCKADDR_IPX)), IPXAddr sa_family = AF_IPX, IPXAddr sa_socket = htons(5150), if (bind(sdServer, (PSOCKADDR) «JPXAddr, sizeof(SOCKADDR_IPX)) == SOCKET_ERROR) { pnntf(bind failed with error Xd\n, WSAGetLastErrorO), return, (getsockname((unsigned) sdServer, (PSOCKADDR) &IPXAddr, &addrlen) == SOCKET_ERR0R) pnntf(getsockname failed with error Xd1, * ' WSAGetLastErrorO), return

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: