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));
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Неявное связывание
Неявное связывание Неявное связывание, или связывание во время загрузки (load-time linking) является простейшей из двух методик связывания. Порядок действий в случае использования Microsoft C++ следующий:1. После того как собраны все необходимые для новой DLL функции, осуществляется
Явное связывание
Явное связывание Явное связывание, или связывание во время выполнения (run-time linking), требует, чтобы в программе содержались конкретные указания относительно того, когда именно необходимо загрузить или освободить библиотеку DLL. Далее программа получает адрес запрошенной
Создание сокета
Создание сокета Инициализировав Winsock DLL, вы можете использовать стандартные (Berkeley Sockets) функции для создания сокетов и соединений, обеспечивающих взаимодействие серверов с клиентами или взаимодействие равноправных узлов сети между собой.Используемый в Winsock тип данных
Связывание сокета
Связывание сокета Следующий шаг заключается в привязке сокета к его адресу и конечной точке (endpoint) (направление канала связи от приложения к службе). Вызов socket, за которым следует вызов bind, аналогичен созданию именованного канала. Однако не существует имен, используя
17.3.1. Создание сокета
17.3.1. Создание сокета Новые сокеты создаются системным вызовом socket(), который возвращает файловый дескриптор для неинициализированного сокета. При создании сокет привязывается к определенному протоколу, однако соединение для сокета не устанавливается. На данном этапе
17.6.1. Создание UDP-сокета
17.6.1. Создание UDP-сокета Как и любой другой сокет, UDP-сокет создается с помощью функции socket(), однако второй аргумент должен быть SOCK_DGRAM, а последний — либо IPPROTO_UDP, либо просто ноль (так как UDP является стандартным IP-дейтаграммным протоколом).После создания сокета ему
11.9.3 Связывание
11.9.3 Связывание Сервер DHCP хранит таблицу соответствия между клиентами и их конфигурационными параметрами. Связывание заключается в назначении каждому клиенту IP-адреса и набора конфигурационных
R.3.3 Программа и связывание
R.3.3 Программа и связывание Программа состоит из одного или нескольких файлов, связываемых вместе (§R.2). Файл состоит из последовательности описаний. Имя с файловой областью видимости, которое явно описано как static, является локальным в своей единице трансляции и может
Динамическое связывание
Динамическое связывание Упрощенно говоря, динамическое связывание, или динамическая привязка, - это подход, с помощью которого можно создавать экземпляры заданного типа и вызывать их члены в среде выполнения и условиях, когда во время компиляции о типе еще ничего не
9.1.7. Безопасное связывание A
9.1.7. Безопасное связывание A При использовании перегрузки складывается впечатление, что в программе можно иметь несколько одноименных функций с разными списками параметров. Однако это лексическое удобство существует только на уровне исходного текста. В большинстве
4. Создание объектной модели и ее связывание с моделью данных при помощи ERwin Translation Wizard
4. Создание объектной модели и ее связывание с моделью данных при помощи ERwin Translation Wizard 4.1. Язык UML Классический структурный подход к созданию ИС предполагает последовательную реализацию этапов анализа, проектирования, создания модулей, объединения модулей в единую
Динамическое создание и повторное связывание
Динамическое создание и повторное связывание Что не было показано при описании структуры объектов периода выполнения, так это в высшей степени динамичная природа настоящей ОО-модели. Статическая и ориентированная на стеки политика управления объектами характерна для
Связывание с АТД
Связывание с АТД Класс, как неоднократно говорилось, является реализацией АТД, заданного формальной спецификацией или неявно подразумеваемого. В начале лекции отмечалось, что утверждения можно рассматривать, как способ введения в класс семантических свойств, лежащих в
Динамическое связывание
Динамическое связывание Динамическое связывание дополнит переопределение, полиморфизм и статическую типизацию, создавая базисную тетралогию
Типизация и связывание
Типизация и связывание Хотя как читатель этой книги вы наверняка отличите статическую типизацию от статического связывания, есть люди, которым подобное не под силу. Отчасти это может быть связано с влиянием языка Smalltalk, отстаивающего динамический подход к обеим задачам