if (start_resp_from_server) {
while (read_resp_from_server(&mess_ret)) {
if (mess_ret.response == r_success) {
fwrite(&mess_ret.cdc_entry_data, sizeof(cdc_entry), 1, work_file);
entries_matching++;
} else {
break;
}
} /* while */
} else {
fprintf(stderr, "Server not responding\n");
}
} else {
fprintf (stderr, "Server not accepting requests\n");
}
4. Следующая проверка ищет, есть ли совпадения с заданным значением. Далее вызов fseek
переводит указатель в файле work_file
на место записи следующей порции данных.
if (entries_matching == 0) {
fclose(work_file);
work_file = (FILE *)0;
return(ret_val);
}
(void)fseek(work_file, 0L, SEEK_SET);
5. Если это не первый вызов функции поиска для данного конкретного элемента, программа проверяет, были ли уже найдены совпадения. В заключение в структуру ret_val
читается следующий совпадающий элемент. Предшествующие проверки гарантируют наличие совпадающего элемента.
} else {
/* не *first_call_ptr */
if (entries_matching == 0) {
fclose(work_file);
work_file = (FILE *)0;
return(ret_val);
}
}
fread(&ret_val, sizeof(cdc_entry), 1, work_file);
entries_matching--;
return(ret_val);
}
Интерфейс сервера server.c
Если у клиента есть интерфейс для обращения к программе app_ui.c, серверу также нужна программа для управления (переименованной) программой cd_access.c, теперь cd_dbm.c. Далее приведена функция main сервера.
1. Начните с объявления нескольких глобальных переменных, прототипа функции process_command
и функции перехвата сигнала для обеспечения чистого завершения.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "cd_data.h"
#include "cliserv.h"
int save errno;
static int server_running = 1;
static void process_command(const message_db_t mess_command);
void catch_signals {
server_running = 0;
}
2. Теперь переходите к функции main
. После проверки успешного завершения подпрограмм захвата сигнала программа проверяет, передали ли вы -i
в командной строке. Если да, она создаст новую базу данных. Если вызов подпрограммы database_initialize
в файле cd_dbm.c завершится аварийно, будет выведено сообщение об ошибке. Если все хорошо и сервер работает, любые запросы от клиента направляются функции process_command
, которую вы вскоре увидите.
int main(int argc, char *argv[]) {
struct sigaction new_action, old_action;
message_db_t mess command;
int database_init_type = 0;
new_action.sa_handler = catch_signals;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
if ((sigaction(SIGINT, &new_action, &old_action) != 0) ||
(sigaction(SIGHUP, &new_action, &old_action) != 0) ||
(sigaction(SIGTERM, &new_action, &old_action) != 0)) {
fprintf(stderr, "Server startup error, signal catching failed\n");
exit(EXIT_FAILURE);
}
if (argc > 1) {
argv++;
if (strncmp("-i", *argv, 2) == 0) database_init_type = 1;
}
if (!database_initialize(database_init_type)) {
fprintf(stderr, "Server error :-\
could not initialize database\n");
exit (EXIT_FAILURE);
}
if (!server starting) exit(EXIT_FAILURE);
while(server_running) {
if (read_request_from_client(&mess_command)) {
process_command(mess_command);
} else {
if (server_running) fprintf(stderr,