Основы программирования в Linux
Основы программирования в Linux читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
int del_cdt_entry(const char *cd_catalog_ptr, const int track_no);cdc_entry search_cdc_entry(const char *cd_catalog_ptr, int *first_call_ptr);В этих функциях очень удобно провести резкую границу между клиентом и сервером.
В реализации в виде единого процесса вы можете разделить приложение на две части (рис. 13.6), несмотря на то, что оно компилировалось как единая программа.

Рис. 13.6
В клиент-серверную версию приложения вы хотите включить несколько именованных каналов и сопроводительный программный код для связи двух основных частей приложения. На рис. 13.7 показана необходимая структура.

Рис. 13.7
В данной реализации подпрограммы интерфейса и клиента, и сервера помещены в один файл pipe_imp.c. Это сохраняет в едином файле весь программный код, зависящий от применения именованных каналов в клиент-серверной реализации. Форматирование и упаковка передаваемых данных хранятся отдельно от подпрограмм, реализующих именованные каналы. В результате у вас появятся дополнительные файлы исходного текста программы, но с более логичным разделением. Структура вызовов в приложении показана на рис. 13.8.

Рис. 13.8
Файлы арр_ui.c, client_if.c и pipe_imp.c компилируются и компонуются вместе для получения клиентской программы. Файлы cd_dbm.c, server.c и pipe_imp.c компилируются и компонуются вместе для создания серверной программы. Заголовочный файл cliserv.h действует как заголовочный файл общих определений для связывания обеих программ.
В файлы app_ui.c и cd_dbm.c внесены очень незначительные изменения, в принципе позволяющие разделить приложение на две программы. Поскольку теперь приложение очень большое и существенная часть программного кода не изменилась по сравнению с предыдущей версией, здесь мы покажем только файлы cliserv.h, сlient_if.c и pipe_imp.c.
Сначала рассмотрим cliserv.h. Этот файл определяет клиент-серверный интерфейс. Он необходим и клиентской, и серверной программам.
1. Далее приведены необходимые директивы
#include#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>2. Затем вы определяете именованные каналы. Используйте один канал для сервера и по одному каналу для каждого клиента. Поскольку клиентов может быть несколько, клиентская программа включает идентификатор процесса в имя, таким образом, обеспечивая уникальность канала.
#define SERVER_PIPE "/tmp/server_pipe"#define CLIENT_PIPE "/tmp/client_%d_pipe"#define ERR_TEXT_LEN 803. Реализуйте команды как перечислимые типы, а не как директивы
#defineЭто хорошая возможность для компилятора выполнить дополнительную проверку типов и помочь в отладке приложения, т.к. многие отладчики могут показывать имена перечислимых констант, но не имена, определенные директивой
#defineПервый оператор
typedeftypedef enum { s_create_new_database = 0, s_get_cdc_entry, s_get_cdt_entry, s_add_cdc_entry, s_add_cdt_entry, s_del_cdc_entry, s_del_cdt_entry, s_fmd_cdc_entry} client_request_e;typedef enum { r_success = 0, r_failure, r_find_no_more} server_response_e;4. Далее объявите структуру, которая будет формировать сообщение, передаваемое между двумя процессами в обоих направлениях.
Поскольку на самом деле вам не нужно возвращать
cdc_entrycdt_entrytypedef struct { pid_t client_pid; client_request_e request; server_response_e response; cdc_entry cdc_entry_data; cdt_entry cdt_entry_data; char error_text[ERR_TEXT_LEN + 1];} message_db_t;5. В заключение приведены функции интерфейса канала, выполняющие передачу данных и содержащиеся в файле pipe_imp.c. Они делятся на функции серверной и клиентской стороны, в первом и втором блоках соответственно.
int server_starting(void);void server_ending(void);int read_request_from_client(message_db_t *rec_ptr);int start_resp_to_client(const message_db_t mess_to_send);int send_resp_to_client(const message_db_t mess_to_send);void end_resp_to_client(void);int client_starting(void);void client_ending(void);int send_mess_to_server(message_db_t mess_to_send);int start_resp_from_server(void);int read_resp_from_server(message_db_t *rec_ptr);void end_resp_from_server(void);Мы разделим последующее обсуждение на функции клиентского интерфейса и детали серверных и клиентских функций, хранящихся в файле pipe_imp.c, и при необходимости будем обращаться к исходному программному коду.
Функции интерфейса клиента
Рассмотрим файл clientif.c. Он предоставляет "поддельные" версии подпрограмм доступа к базе данных. Они кодируют запрос в структуре
message_db_t
