Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
• Говорят, что протоколы обеспечивают упорядочение, если они гарантируют доставку данных в том же порядке, в котором они были отправлены.
• Протоколы предоставляют защиту от ошибокв том случае, если они автоматически отбрасывают поврежденные сообщения и подготавливаются к повторной передаче данных.
• Потоковые протоколыраспознают только байтовые границы. Последовательности байтов могут разделяться и доставляться адресату по мере появления данных.
• Пакетные протоколыобрабатывают пакеты данных, сохраняя границы пакета и доставляя полные пакеты получателям. Пакетные протоколы, как правило, требуют определенного максимального размера пакета.
Хотя каждый из перечисленных атрибутов не зависит от остальных, в приложениях употребляются только два основных типа протоколов. Дейтаграммныепротоколы являются механизмами пакетной передачи, не предоставляя при этом ни упорядочения, ни защиты от ошибок. Широко используется дейтаграммный протокол UDP, являющийся представителем семейства протоколов TCP/IP. Потоковыепротоколы (такие как TCP из TCP/IP) — это протоколы потоковой передачи, которые обеспечивают и упорядочение, и защиту от ошибок.
Несмотря на то что дейтаграммные протоколы вроде UDP, несомненно, полезны [118] Многие высокоуровневые протоколы, такие как BOOTP и NFS, построены на основе UDP.
, мы остановимся на применении потоковых протоколов, поскольку их легче использовать для большинства приложений. Подробное описание разработки протоколов и различий между их отдельными видами можно найти во многих книгах, например, [33] и [34].
17.1.4. Адреса
Поскольку каждый протокол поддерживает собственное определение сетевого адреса, интерфейс сокетов должен абстрагировать адреса. В качестве базовой формы адреса используется структура struct sockaddr
; его содержимое устанавливается по-разному для каждого семейства адресов. Передавая struct sockaddr
в системный вызов, процесс также указывает размер передаваемого адреса. Тип socklen_t
определяется как число, достаточно большое для хранения размера любого сокета, который используется системой.
Все типы struct sockaddr
соответствуют приведенному ниже определению.
#include
struct sockaddr {
unsigned short sa_family;
char sa_data[MAXSOCKADDRDATA];
}
Первые два байта (размер short
) указывают семейство адресов, к которому относится данный адрес. Перечень стандартных адресных семейств, используемых приложениями Linux, приведен в табл. 17.1.
Таблица 17.1. Семейства протоколов и адресов
Адрес | Протокол | Описание протокола |
---|---|---|
AF_UNIX |
PF_UNIX |
Домен Unix. |
AF_INET |
PF_INET |
TCP/IP (версия 4). |
AF_INET6 |
PF_INET6 |
TCP/IP (версия 6). |
AF_AX25 |
PF_AX25 |
AX.25, используется радиолюбителями. |
AF_IPX |
PF_IPX |
Novell IPX. |
AF_APPLETALK |
PF_APPLETALK |
AppleTalk DDS. |
AF_NETROM |
PF_NETROM |
NetROM, используется радиолюбителями. |
17.2. Служебные функции
Во всех примерах этого раздела используются две функции: copyData()
и die()
. Функция copyData()
считывает данные из одного файлового дескриптора и записывает их в какой-то другой дескриптор (до тех пор, пока имеются данные для чтения). Функция die()
вызывает perror()
и завершает программу. Мы ввели обе указанные функции в файл sockutil.с
для того, чтобы сделать обучающие программы немного проще. Для справки ниже показана реализация двух данных функций.
1: /* sockutil.с */
2:
3: #include
4: #include
5: #include
6:
7: #include "sockutil.h"
8:
9: /* выдает сообщение об ошибке через функцию perror() и прекращает работу программы */
10: void die(char * message) {
11: perror(message);
12: exit(1);
13: }
14:
15: /* Копирует данные из дескриптора файла 'from' в дескриптор файла
16: 'to' до полного завершения копирования. Выходит из программы, если
17: происходит ошибка. Предполагается, что для обоих файлов установлено
18: блокирующее чтение и запись. */
19: void copyData(int from, int to) {
20: char buf[1024];
21: int amount;
22:
23; while ((amount = read(from, buf, sizeof(buf))) > 0) {
24: if (write(to, buf, amount) != amount) {
25: die("write");
26: return;
27: }
28: }
29: if (amount < 0)
30: die("read");
31: }
17.3. Основные действия с сокетами
Подобно большинству остальных ресурсов Linux сокеты реализуются через файловую абстракцию. Они создаются при помощи системного вызова socket()
, который возвращает файловый дескриптор. После соответствующей инициализации сокета данный дескриптор может использоваться для запросов read()
и write()
, как и любой другой файловый дескриптор. Когда процесс завершает работу с сокетом, его необходимо закрыть через функцию close()
для того, чтобы освободить все ресурсы, ассоциированные с ним.
В настоящем разделе представлены основные системные вызовы для создания и инициализации сокетов для любого протокола. Для того чтобы не зависеть от протоколов, информация в некоторой степени абстрагирована, по этой же причине мы не приводим примеры. Следующие два раздела посвящены применению сокетов в двух различных протоколах (домен Unix и TCP/IP). Здесь вы найдете подробные примеры использования большинства системных вызовов, описанных ниже.
17.3.1. Создание сокета
Новые сокеты создаются системным вызовом socket()
, который возвращает файловый дескриптор для неинициализированного сокета. При создании сокет привязывается к определенному протоколу, однако соединение для сокета не устанавливается. На данном этапе еще невозможно считывать информацию из сокета и записывать в него.
#include
int socket(int domain, int type, int protocol);
Подобно open()
, функция socket()
возвращает значение меньше 0, если имела место ошибка, и файловый дескриптор, больший или равный нулю, если все прошло благополучно. Три параметра устанавливают протокол, который нужно использовать.
Первый параметр указывает семейство протоколов и, как правило, принимает одно из значений, перечисленных в табл. 17.1.
Следующий параметр type
может иметь одно из значений: SOCK_STREAM
, SOCK_DGRAM
или SOCK_RAW
. [119] Допустимы еще несколько значений данного параметра, однако они редко применяются в коде приложений.
Здесь SOCK_STREAM
указывает потоковый протокол из данного семейства, a SOCK_DGRAM
специфицирует дейтаграммный протокол из того же семейства. Параметр SOCK_RAW
предоставляет возможность передавать пакеты прямо в драйвер сетевого устройства, что позволяет пользовательским приложениям поддерживать сетевые протоколы, которые не воспринимаются ядром.
Интервал:
Закладка: