27.3.2. Создание и связывание сокета

27.3.2. Создание и связывание сокета

Основная задача управляющих функций — организовать взаимодействие двух компьютеров, точнее процессов, а также завершить сеанс связи этих процессов. К управляющим функциям относятся функции:

socket() — создание сокета;

bind() — связывание сокета;

close() и shutdown() — завершение сеанса связи.

Начнем по порядку, а именно, с функции socket(). Ее прототип следующий:

#include <sys/types.h>

#include <sys/socket.h>

extern int socket(int __domain, int __type,

 int __protocol) __THROW;

Первый аргумент определяет набор протоколов. Особо вдаваться в подробности не будем — просто всегда в качестве параметра domain передавайте значение AF_INET, что означает использование стека протоколов TCP/IP.

Аргумент type позволяет установить режим работы: с установлением соединения и без такового — значения SOCK_STREAM и SOCK_DGRAM соответственно. Для непосредственного доступа к протоколам IPv4 используется параметр SOCK_RAW. Для его использования нужно подключить заголовочный файл:

#include <netinet/in.h>

Третий параметр лучше всего установить равным 0. В этом случае будет выбран протокол по умолчанию в зависимости от режима работы:

TCP, если мы выбрали режим SOCK_STREAM;

UDP, если мы выбрали SOCK_DGRAM.

Если вы установили значение SOCK_RAW, вы можете указывать в качестве последнего параметра непосредственно значения из файла /etc/protocols. Фрагмент этого файла приведен ниже.

Листинг 27.2. Фрагмент файла /etc/protocols

ip   0 IP   # Протокол Интернета

icmp 1 ICMP # Протокол ICMP

igmp 2 IGMP # Протокол IGMP

            # (Internet Group Management Protocol)

ggp  3 GGP  # Протокол GGP (gateway-gateway )

tcp  6 TCP  # Протокол TCP

udp 17 UDP  # Протокол UDP

Если сокет создан успешно, функция возвращает дескриптор сокета — целое положительное число. В случае ошибки функция возвращает значение -1 (отрицательное число). Вот небольшой пример:

int sock;

sock = socket(AF_INET, SOCK_STREAM, 0);

if (sock==-1) {

 printf("Ошибка при создании сокета ");

 exit(1);

}

Чтобы связать созданный нами сокет с локальным портом, например, 1234, нужно использовать системный вызов bind():

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

extern int bind(int fd, struct sockaddr *addr,

 socklen_t len) __THROW;

Первый аргумент функции задает дескриптор нашего сокета. Второй — это указатель на структуру типа sockaddr. Все структуры данного типа определены в файле socket.h:

# define __SОСKADDR_ALLTYPES

 __SOCKADDR_ONETYPE (sockaddr)

 __SOCKADDR_ONETYPE (sockaddr_at)

 __SОСKADDR_ONETYPE (sockaddr_ax25)

 __SOCKADDR_ONETYPE (sockaddr_dl)

 __SOCKADDR_ONETYPE (sockaddr_eon)

 __SОСKADDR_ONETYPE (sockaddr_in)

 __SOCKADDR_ONETYPE (sockaddr_in6)

 __SОСKADDR_ONETYPE (sockaddr_inarp)

 __SOCKADDR_ONETYРЕ (sockaddr_ipx)

 __SОСKADDR_ONETYPE (sockaddr_iso)

 __SОСKADDR_ONETYPE (sockaddr_ns)

 __SOCKADDR_ONETYPE (sockaddr_un)

 __SOCKADDR_ONETYPE (sockaddr_x25)

Мы программируем для сети TCP/IP, поэтому будем использовать структуру sockaddr_in (для IPv4) или sockaddr_in6 (для IPv6).

Последний аргумент — это длина выбранной нами структуры (sockaddr_in) в байтах.

Структура sockaddr_in определена в файле in.h так:

struct sockaddr_in {

 __SОСKADDR_COMMON(sin_);

 in_port_t sin_port; /* Номер порта */

 struct in_addr sin_addr; /* IP-адрес */

 unsigned char sin_zero[sizeof (struct sockaddr) -

  __SОСKADDR_COMMON_SIZE -

  sizeof(in_port_t) - sizeof (struct in_addr)];

};

/* для IPv6. */

struct sockaddr_in6 {

 __SОСKADDR_COMMON(sin6_);

 in_port_t sin6_port; /* Порт транспортного уровня */

 uint32_t sin6_flowinfo; /* Информация потока IPv6 */

 struct in6_addr sin6_addr; /* адрес IPv6 */

 uint32_t sin6_scope_id; /* IPv6-идентификатор */

};

Поля структуры sockaddr_in означают следующее:

sin_ — набор используемых протоколов. Так как мы используем TCP/IP, данное поле должно содержать значение AF_INET;

sin_port — номер порта;

sin_addr — структура, определяющая адрес узла;

sin_zero — обычно не используется.

Структура struct in_addr, определяющая адрес узла, также описана в файле in.h:

struct in_addr {

 in_addr_t s_addr;

};

Обычно поле s_addr должно принимать значение INADDR_ANY — сейчас поясню почему. Структура sockaddr_in должна быть заполнена ДО вызова функции bind(). Если поле sin_addr.s_addr принимает значение INADDR_ANY, то функция bind() автоматически привяжет к сокету адрес локального компьютера и нам не нужно будет указывать его явно — так наша программа будет универсальной.

Функция bind() возвращает 0 в случае успеха, и -1, если произошла ошибка. Вот небольшой пример использования этой функции:

struct sockaddr_in client;

...

client.sin_family = AF_INET;

client.sin_addr.s_addr = INADDR_ANY;

client.sin_port = 1235;

bind(sock, (struct sockaddr *)&client, sizeof(client));

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

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

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

R.3.3 Программа и связывание

Из книги Справочное руководство по C++ автора Страустрап Бьярн

R.3.3 Программа и связывание Программа состоит из одного или нескольких файлов, связываемых вместе (§R.2). Файл состоит из последовательности описаний. Имя с файловой областью видимости, которое явно описано как static, является локальным в своей единице трансляции и может


Динамическое связывание

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

Динамическое связывание Упрощенно говоря, динамическое связывание, или динамическая привязка, - это подход, с помощью которого можно создавать экземпляры заданного типа и вызывать их члены в среде выполнения и условиях, когда во время компиляции о типе еще ничего не


Динамическое создание и повторное связывание

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Динамическое создание и повторное связывание Что не было показано при описании структуры объектов периода выполнения, так это в высшей степени динамичная природа настоящей ОО-модели. Статическая и ориентированная на стеки политика управления объектами характерна для


Связывание с АТД

Из книги Системное программирование в среде Windows автора Харт Джонсон М

Связывание с АТД Класс, как неоднократно говорилось, является реализацией АТД, заданного формальной спецификацией или неявно подразумеваемого. В начале лекции отмечалось, что утверждения можно рассматривать, как способ введения в класс семантических свойств, лежащих в


Динамическое связывание

Из книги TCP/IP Архитектура, протоколы, реализация (включая IP версии 6 и IP Security) автора Фейт Сидни М

Динамическое связывание Динамическое связывание дополнит переопределение, полиморфизм и статическую типизацию, создавая базисную тетралогию


Типизация и связывание

Из книги BPwin и Erwin. CASE-средства для разработки информационных систем автора Маклаков Сергей Владимирович

Типизация и связывание Хотя как читатель этой книги вы наверняка отличите статическую типизацию от статического связывания, есть люди, которым подобное не под силу. Отчасти это может быть связано с влиянием языка Smalltalk, отстаивающего динамический подход к обеим задачам


Неявное связывание

Из книги О чём не пишут в книгах по Delphi автора Григорьев А. Б.

Неявное связывание Неявное связывание, или связывание во время загрузки (load-time linking) является простейшей из двух методик связывания. Порядок действий в случае использования Microsoft C++ следующий:1. После того как собраны все необходимые для новой DLL функции, осуществляется


Явное связывание

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

Явное связывание Явное связывание, или связывание во время выполнения (run-time linking), требует, чтобы в программе содержались конкретные указания относительно того, когда именно необходимо загрузить или освободить библиотеку DLL. Далее программа получает адрес запрошенной


Создание сокета

Из книги C++ для начинающих автора Липпман Стенли

Создание сокета Инициализировав Winsock DLL, вы можете использовать стандартные (Berkeley Sockets) функции для создания сокетов и соединений, обеспечивающих взаимодействие серверов с клиентами или взаимодействие равноправных узлов сети между собой.Используемый в Winsock тип данных


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

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

Связывание сокета Следующий шаг заключается в привязке сокета к его адресу и конечной точке (endpoint) (направление канала связи от приложения к службе). Вызов socket, за которым следует вызов bind, аналогичен созданию именованного канала. Однако не существует имен, используя


11.9.3 Связывание

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

11.9.3 Связывание Сервер DHCP хранит таблицу соответствия между клиентами и их конфигурационными параметрами. Связывание заключается в назначении каждому клиенту IP-адреса и набора конфигурационных


4. Создание объектной модели и ее связывание с моделью данных при помощи ERwin Translation Wizard

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

4. Создание объектной модели и ее связывание с моделью данных при помощи ERwin Translation Wizard 4.1. Язык UML Классический структурный подход к созданию ИС предполагает последовательную реализацию этапов анализа, проектирования, создания модулей, объединения модулей в единую


17.3.1. Создание сокета

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

17.3.1. Создание сокета Новые сокеты создаются системным вызовом socket(), который возвращает файловый дескриптор для неинициализированного сокета. При создании сокет привязывается к определенному протоколу, однако соединение для сокета не устанавливается. На данном этапе


17.6.1. Создание UDP-сокета

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

17.6.1. Создание UDP-сокета Как и любой другой сокет, UDP-сокет создается с помощью функции socket(), однако второй аргумент должен быть SOCK_DGRAM, а последний — либо IPPROTO_UDP, либо просто ноль (так как UDP является стандартным IP-дейтаграммным протоколом).После создания сокета ему


9.1.7. Безопасное связывание A

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

9.1.7. Безопасное связывание A При использовании перегрузки складывается впечатление, что в программе можно иметь несколько одноименных функций с разными списками параметров. Однако это лексическое удобство существует только на уровне исходного текста. В большинстве