Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
5.5.3. Серверы
Жизненный цикл сервера можно представить так:
1) создание сокета, ориентированного на соединения (функция socket ());
2) назначение сокету адреса привязки (функция bind ());
3) перевод сокета в режим ожидания запросов (функция listen ());
4) прием поступающих запросов (функция accept ());
5) закрытие сокета (функция close ()).
Данные не записываются и не читаются напрямую через серверный сокет. Вместо этого всякий раз, когда сервер принимает запрос на соединение, ОС Linux создает отдельный сокет, используемый для передачи данных через это соединение.
Серверному сокету необходимо с помощью функции bind()
назначить адрес, чтобы клиент смог его найти. Первым аргументом функции является дескриптор сокета. Второй аргумент — это указатель на адресную структуру, формат которой будет зависеть от выбранного семейства адресов. Третий аргумент — это длина адресной структуры в байтах. После получения адреса сокет, ориентированный на соединения, должен вызвать функцию listen()
, тем самым обозначив себя как сервер. Первым аргументом этой функции также является дескриптор сокета. Второй аргумент определяет, сколько запросов может находиться в очереди ожидания. Если очередь заполнена, все последующие запросы отвергаются. Этот аргумент задает не предельное число запросов, которое способен обработать сервер. а максимальное количество клиентов, которые могут находиться в режиме ожидания.
Сервер принимает от клиента запрос на подключение, вызывая функцию accept()
. Первый ее аргумент — это дескриптор сокета. Второй аргумент указывает на адресную структуру, заполняемую адресом клиентского сокета. Третий аргумент содержит длину (в байтах) адресной структуры. Функция accept()
создает новый сокет для обслуживания клиентского соединения и возвращает его дескриптор. Исходный серверный сокет продолжает принимать запросы от клиентов. Чтобы прочитать данные из сокета, не удалив их из входящей очереди, воспользуйтесь функцией recv()
. Она принимает те же аргументы, что и функция read(), плюс дополнительный аргумент FLAGS
. Флаг MSG_PEEK
задает режим "неразрушающего" чтения, при котором прочитанные данные остаются в очереди.
5.5.4. Локальные сокеты
Сокеты, соединяющие процессы в пределах одного компьютера, работают в локальном пространстве имен ( PF_LOCAL
или PF_UNIX
, это синонимы). Такие сокеты называются локальными или UNIX-сокетами . Их адресами являются имена файлов, указываемые только при создании соединения.
Имя сокета задается в структуре типа sockaddr_un
. В поле sun_family
необходимо записать константу AF_LOCAL
, указывающую на то, что адрес находится в локальном пространстве имен. Поле sun_path
содержит путевое имя файла и не может превышать 108 байтов. Длина структуры sockaddr_un
вычисляется с помощью макроса SUN_LEN()
. Допускается любое имя файла, но процесс должен иметь право записи в каталог, где находится файл. При подключении к сокету процесс должен иметь право чтения файла. Несмотря на то что файловая система может экспортироваться через NFS на разные компьютеры, только процессам, работающим в пределах одного компьютера, разрешается взаимодействовать друг с другом посредством локальных сокетов.
При работе в локальном пространстве имен допускается только протокол с номером 0.
Локальный сокет является частью файловой системы, поэтому он отображается командой ls
(обратите внимание на букву s
в строке режима):
% ls -l /tmp/socket
srwxrwx--x 1 user group 0 Nov 13 19:16 /tmp/socket
Если локальный сокет больше не нужен, его файл можно удалить с помощью функции unlink()
.
5.5.5. Примеры программ, работающих с локальными сокетами
Работу с локальными сокетами мы проиллюстрируем двумя программами. Первая (листинг 5.10) — это сервер. Он создает локальный сокет и переходит в режим ожидания запросов на подключение. Приняв запрос, сервер читает сообщения из сокета и отображает на на экране, пока соединение не будет закрыто. Если поступает сообщение "quit", сервер удаляет сокет и завершает свою работу. Программа socket-server
ожидает путевое имя сокета в командной строке.
#include
#include
#include
#include
#include
#include
/* Чтение сообщений из сокета и вывод их на экран. Функция
продолжает работу до тех пор, пока сокет не будет закрыт.
Функция возвращает 0, если клиент послал сообщение "quit",
в противном случае возвращается ненулевое значение. */
int server(int client_socket) {
while (1) {
int length;
char* text;
/* Сначала читаем строку, в которой записана длина сообщения.
Если возвращается 0, клиент закрыл соединение. */
if (read(client_socket, &length, sizeof(length)) == 0)
return 0;
/* Выделение буфера для хранения текста. */
text = (char*)malloc(length);
/* Чтение самого сообщения и вывод его на экран. */
read(client_socket, text, length);
printf("%s\n", text);
/* Очистка буфера. */
free(text);
/* Если клиент послал сообщение "quit.", работа сервера
завершается. */
if (!strcmp(text, "quit"))
return 1;
}
}
int main(int argc, char* const argv[]) {
const char* const socket_name = argv[1];
int socket_fd;
struct sockaddr_un name;
int client_sent_quit_message;
/* Создание локального сокета. */
socket_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
/* Переход в режим сервера. */
name.sun_family = AF_LOCAL;
strcpy(name.sun_path, socket_name);
bind(socket_fd, SUN_LEN(&name));
/* Ожидание запросов. */
listen(socket_fd, 5);
/* Непрерывный прием запросов на подключение. Для каждого
клиента вызывается функция server(). Цикл продолжается,
пока не будет получено сообщение "quit". */
do {
struct sockaddr_un client_name;
socklen_t client_name_len;
int client_socket_fd;
/* Прием запроса. */
client_socket_fd =
accept(socket_fd, &client_name, &client_name_len);
/* Обработка запроса. */
client_sent_quit_message = server(client_socket_fd);
/* Закрытие серверной стороны соединения. */
close(client_socket_fd);
} while(!client_sent_quit_message);
/* Удаление файла локального сокета. */
close(socket_fd);
unlink(socket_name);
return 0;
}
Клиентская программа, показанная в листинге 5.11, подключается к локальному сокету и посылает сообщение. Путевое имя сокета и текст сообщения задаются в командной строке.
#include
#include
#include
Интервал:
Закладка: