4. Далее объявите структуру, которая будет формировать сообщение, передаваемое между двумя процессами в обоих направлениях.
Примечание
Поскольку на самом деле вам не нужно возвращать
cdc_entry
и
cdt_entry
в одном ответе, вы могли бы сделать их объединением (union). Но для простоты можно оставить их отдельными элементами, кроме того, в этом случае легче поддерживать программный код.
typedef 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
и затем применяют подпрограммы из файла pipe_imp.c для передачи запроса серверу. Такой подход позволит вам внести минимальные изменения в первоначальный файл app_ui.c.
Интерпретатор клиента
1. В этом файле реализовано девять функций для работы с базой данных, объявленных в файле cd_data.h. Делает он это передачей запросов серверу и затем возвратом ответа сервера из функции, действуя как посредник. Файл начинается с файлов
#include
и констант.
#define _POSIX_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "cd_data.h"
#include "cliserv.h"
2. Статическая
переменная
mypid
уменьшает количество вызовов
getpid
, требуемых в противном случае. Мы применяем локальную функцию
read_one_response
для устранения дублирующегося программного кода.
static pid_t mypid;
static int read_one_response(message_db_t *rec_ptr);
3. Подпрограммы
database_initialize
и
close
все еще вызываются, но теперь используются, соответственно, для инициализации клиентского интерфейса каналов и удаления лишних именованных каналов, когда клиент завершил выполнение.
int database_initialize(const int new_database) {
if (!client_starting) return(0);
mypid = getpid;
return(1);
}
/* инициализация базы данных */
void database_close(void) {
client_ending;
}
4. Подпрограмма
get_cdc_entry
вызывается для получения элемента каталога из базы данных по заданному названию компакт-диска в каталоге. В ней вы кодируете запрос в структуре
message_db_t
и передаете его на сервер. Далее вы считываете обратно ответ в другую структуру типа
message_db_t
. Если элемент найден, он включается в структуру
message_db_t
как структура типа
cdc_entry
, поэтому вы можете передать соответствующую часть структуры.