Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Последний параметр устанавливает протокол для использования с учетом всех ограничений, введенных первыми двумя параметрами. Как правило, значение этого параметра равно 0, что позволяет ядру использовать стандартный протокол установленного типа из указанного семейства. В табл. 17.2 перечислены некоторые допустимые протоколы для семейства PF_INET
. Стандартными протоколами здесь считаются IPPROTO_TCP
(потоковый) и IPPROTO_UDP
(дейтаграммный).
Таблица 17.2. Протоколы IP
Протокол | Описание |
---|---|
IPPROTO_ICMP |
Internet Control Message Protocol (протокол управляющих сообщений в сети Internet) для IPv4. |
IPPROTO_ICMPV6 |
Internet Control Message Protocol (протокол управляющих сообщений в сети Internet) для IPv6. |
IPPROTO_IPIP |
Тоннели IPIP |
IPPROTO_IPV6 |
Заголовки IPv6. |
IPPROTO_RAW |
Пакеты Raw IP. |
IPPROTO_TCP |
Transmission Control Protocol (TCP) (протокол управления передачей). |
IPPROTO_UDP |
User Datagram Protocol (UDP) (протокол передачи дейтаграмм пользователя). |
17.3.2. Установка соединений
После создания потокового сокета его необходимо присоединить к чему-то часто используемому. Установка соединений сокетов является в большой степени несимметричной задачей, поскольку каждая сторона проводит соединение по-разному. Одна сторона получает сокет, который готов к соединению, и затем ожидает кого-либо для того, чтобы присоединиться к нему. Эту функцию, как правило, выполняют серверные приложения, которые однажды активизируются и постоянно продолжают работать, ожидая подключения со стороны других процессов.
Клиентские процессы, в свою очередь, создают сокет, сообщают системе адрес, к которому они хотят подключиться, и после этого пытаются установить соединение. Как только сервер (ожидающий клиента) принимает попытку соединения, устанавливается соединение между двумя сокетами. После этого сокет может использоваться для двусторонней связи.
17.3.3. Связывание адреса с сокетом
И серверный, и клиентский процессы должны сообщить системе, какой адрес использовать для сокета. Прикрепление адреса к локальной стороне сокета называется связываниемсокета и выполняется через системный вызов bind()
.
#include
int bind(int sock, struct sockaddr * my_addr, socklen_t addrlen);
Первый параметр — это связываемый сокет, остальные параметры задают адрес для локальной конечной точки.
17.3.4. Ожидание соединений
После создания сокета сервер привязывает к нему адрес с помощью функции bind()
. Далее процесс сообщает системе путем вызова функции listen()
, что он готов разрешить другим процессам соединение с данным сокетом (по указанному адресу). Если сокет привязан к адресу, ядро получает возможность обрабатывать попытки соединения с данным адресом, поступающие от процессов. Однако соединение не устанавливается немедленно. Слушающий процесс сначала должен согласиться с попыткой соединения через системный вызов accept()
. До тех пор, пока новая попытка соединения с определенным адресом не принята, она называется ожидающим соединением.
Как правило, функция accept()
блокируется до тех пор, пока к ней не пытается присоединиться некоторый клиентский процесс. Если сокет был помечен как неблокируемый через fcntl()
, то функция accept()
возвращает значение EAGAIN
в том случае, если нет ни одного доступного клиентского процесса [120] Системный вызов connect() может также быть неблокируемым, что позволит пользователям гораздо быстрее открывать несколько TCP соединений (он позволяет продолжать работу программы, в то время как выполняется процесс синхронизации TCP). Подробности по этой теме можно найти в [33].
. Системные вызовы select()
, poll()
и epoll
могут использоваться для указания, ждать ли соединению обработки (эти вызовы помечают сокет как готовый для считывания) [121] Различные формы select() помечают сокет как открытый для чтения, тогда как accept() не может блокировать его, даже если сокет не помечен как неблокируемый. Для обеспечения максимальной переносимости функцию select() необходимо применять только для принятия соглашений с неблокируемыми сокетами, хотя в системе Linux это фактически не нужно. Причины этого подробно рассматриваются в [33].
.
Ниже показаны прототипы listen()
и accept()
.
#include
int listen(int sock, int backlog);
int accept(int sock, struct sockaddr * addr, socklen_t * addrlen);
В обеих функциях предполагается, что первый параметр — это файловый дескриптор. Второй параметр backlog
функции listen()
задает максимальное количество соединений, которые могут одновременно ожидать обработки на данном сокете. Сетевые соединения не устанавливаются до тех пор, пока сервер не примет соединение через accept()
; все входящие соединения считаются приостановленными. Поддерживая небольшое количество ожидающих соединений в очереди, ядро тем самым освобождает серверные процессы от необходимости быть в постоянной готовности принимать соединения. Исторически принято ограничивать в приложениях количество невыполненных заданий пятью, хотя иногда необходимо большее количество. Функция listen()
возвращает ноль в случае успеха и какое-то другое число в случае неудачи.
Вызов accept()
превращает отложенное соединение в установленное. Установленное соединение получает новый файловый дескриптор, который возвращает функция accept()
. Новый дескриптор наследует все атрибуты того сокета, к которому обращалась функция listen()
. Необычное свойство accept()
состоит в том, что она возвращает сетевые ошибки, ожидающие обработки, как ошибки принятия от accept()
[122] Варианты BSD не поддерживают такую модель поведения, в таких системах ошибки проходят без отчетов.
. При возврате ошибки серверы не должны прерывать работу, если параметр errno
принимает одно из следующих значений: ECONNABORTED
, ENETDOWN
, EPROTO
, ENOPROTOOPT
, EHOSTDOWN
, ENONET
, EHOSTUNREACH
, EOPNOTSUPP
или ENETUNREACH
. Все эти ошибки необходимо игнорировать, просто вызвав функцию accept()
на сервере еще раз.
Параметры addr
и addrlen
указывают данные, в которых ядро размещает адрес удаленного (клиентского) конца соединения. В исходном состоянии addrlen
представляет собой целое число, содержащее размер буфера, на который ссылается addr
. Функция accept()
аналогично open() возвращает файловый дескриптор или некоторое отрицательное значение, если возникла ошибка.
17.3.5. Подключение к серверу
Как и серверы, клиенты могут сразу после создания сокета связывать с ним локальный адрес. Обычно клиент пропускает этот шаг, предоставляя ядру присвоить сокету любой подходящий локальный адрес.
Читать дальшеИнтервал:
Закладка: