Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
#include
int accept(int socket, struct sockaddr *address, size_t *address_len);
Системный вызов accept
возвращает управление, когда клиентская программа пытается подключиться к сокету, заданному в параметре socket
. Этот клиент — первый из ждущих соединения в очереди данного сокета. Функция accept
создает новый сокет для обмена данными с клиентом и возвращает его дескриптор. У нового сокета будет тот же тип, что и у сокета сервера, ждущего запросы на соединения.
Предварительно сокету должно быть присвоено имя с помощью системного вызова bind
и у него должна быть очередь запросов на соединение, место для которой выделил системный вызов listen
. Адрес вызывающего клиента будет помещен в структуру sockaddr
, на которую указывает параметр address
. Если адрес клиента не представляет интереса, в этом параметре может задать пустой указатель.
Параметр address_len
задает длину адресной структуры клиента. Если адрес клиента длиннее, чем это значение, он будет урезан. Перед вызовом accept
в параметре address_len
должна быть задана ожидаемая длина адреса. По возвращении из вызова в address_len
будет установлена реальная длина адресной структуры запрашивающего соединение клиента.
Если нет запросов на соединение, ждущих в очереди сокета, вызов accept будет заблокирован (так что программа не сможет продолжить выполнение) до тех пор, пока клиент не сделает запрос на соединение. Вы можете изменить это поведение, применив флаг O_NONBLOCK
в файловом дескрипторе сокета с помощью вызова fcntl
в вашей программе следующим образом:
int flags = fcntl(socket, F_GETFL, 0);
fcntl(socket, F_SETFL, O_NONBLOCK | flags);
Функция accept
возвращает файловый дескриптор нового сокета, если есть запрос клиента, ожидающего соединения, и -1 в случае ошибки. Возможные значения ошибок такие же, как у вызовов bind
и listen
плюс дополнительная константа EWOULDBLOCK
в случае, когда задан флаг O_NONBLOCK
и нет ждущих запросов на соединение. Ошибка EINTR
возникнет, если процесс прерван во время блокировки в функции accept
.
Запросы соединений
Клиентские программы подключаются к серверам, устанавливая соединение между неименованным сокетом и сокетом сервера, ждущим подключений. Делают они это с помощью вызова connect
:
#include
int connect(int socket, const struct sockaddr *address, size_t address_len);
Сокет, заданный в параметре socket
, соединяется с сокетом сервера, заданным в параметре address
, длина которого равна address_len
. Сокет должен задаваться корректным файловым дескриптором, полученным из системного вызова socket
.
Если функция connect
завершается успешно, она возвращает 0, в случае ошибки вернется -1. Возможные ошибки на этот раз включают значения, перечисленные в табл. 15.3.
Таблица 15.3
Значение errno |
Описание |
---|---|
EBADF |
В параметре socket задан неверный файловый дескриптор |
EALREADY |
Для этого сокета соединение уже обрабатывается |
ETIMEDOUT |
Допустимое время ожидания соединения превышено |
ECONNREFUSED |
Запрос на соединение отвергнут сервером |
Если соединение не может быть установлено немедленно, вызов connect
будет заблокирован на неопределенный период ожидания. Когда допустимое время ожидания будет превышено, соединение разорвется и вызов connect
завершится аварийно. Однако, если вызов прерван сигналом, который обрабатывается, connect завершится аварийно (со значением errno, равным EINTR
), но попытка соединения не будет прервана — соединение будет установлено асинхронно и программа должна будет позже проверить, успешно ли оно установлено.
Как и в случае вызова accept
, возможность блокировки в вызове connect
можно исключить установкой в файловом дескрипторе флага O_NONBLOCK
. В этом случае, если соединение не может быть установлено немедленно, вызов connect
завершится аварийно с переменной errno
, равной EINPROGRESS
, и соединение будет выполнено асинхронно.
Хотя асинхронные соединения трудно обрабатывать, вы можете применить вызов select
к файловому дескриптору сокета, чтобы убедиться в том, что сокет готов к записи. Мы обсудим вызов select
чуть позже в этой главе.
Закрытие сокета
Вы можете разорвать сокетное соединение в серверной или клиентской программах, вызвав функцию close
, так же как в случае низкоуровневых файловых дескрипторов. Сокеты следует закрывать на обоих концах. На сервере это нужно делать, когда read
вернет ноль. Имейте в виду, что вызов close
может быть заблокирован, если сокет, у которого есть непереданные данные, обладает типом, ориентированным на соединение, и установленным параметром SOCK_LINGER
. Дополнительную информацию об установке параметров сокета вы узнаете позже в этой главе.
Обмен данными с помощью сокетов
Теперь, когда мы описали основные системные вызовы, связанные с сокетами, давайте повнимательнее рассмотрим программы-примеры. Вы попытаетесь переработать их, заменив сокет файловой системы сетевым сокетом. Недостаток сокета файловой системы состоит в том, что если автор не использует полное имя файла, он создается в текущем каталоге серверной программы. Для того чтобы сделать его полезным в большинстве случаев, следует создать сокет в общедоступном каталоге (например, /tmp), подходящем для сервера и его клиентов. В случае сетевых серверов достаточно выбрать неиспользуемый номер порта.
Для примера выберите номер порта 9734. Это произвольный выбор, позволяющий избежать использования портов стандартных сервисов (вы не должны применять номера портов, меньшие 1024, поскольку они зарезервированы для системного использования). Другие номера портов с обеспечиваемыми ими сервисами часто приводятся в системном файле /etc/services. При написании программ, использующих сокеты, всегда выбирайте номер порта, которого нет в этом файле конфигурации.
Вам следует знать, что в программах client2.c и server2.c умышленно допущена ошибка, которую вы устраните в программах client3.c и server3.c. Пожалуйста, не используйте текст примеров client2.c и server2.c в собственных программах.
Вы будете выполнять ваши серверную и клиентскую программы в локальной сети, но сетевые сокеты полезны не только в локальной сети, любая машина с подключением к Интернету (даже по модемной линии связи) может применять сетевые сокеты для обмена данными с другими компьютерами. Программу, основанную на сетевых подключениях, можно применять даже на изолированном компьютере с ОС UNIX, т. к. такой компьютер обычно настроен на использование виртуальной сети или внутренней петли (loopback network), включающей только его самого. Для демонстрационных целей данный пример использует виртуальную сеть, которая может быть также полезна для отладки сетевых приложений, поскольку она устраняет любые внешние сетевые проблемы.
Читать дальшеИнтервал:
Закладка: