"Server ended — can not read pipe\n");
server_running = 0;
}
} /* while */
server_ending;
exit(EXIT_SUCCESS);
}
3. Любые сообщения клиентов направляются в функцию process_command
, где они обрабатываются в операторе case
, который выполняет соответствующие вызовы из файла cd_dbm.c.
static void process_command(const message_db_t comm) {
message_db_t resp;
int first_time = 1;
resp = comm; /* копирует команду обратно,
затем изменяет resp, как требовалось */
if (!start_resp_to_client(resp)) {
fprintf(stderr, "Server Warning:
start_resp_to_client %d failed\n", resp.client_pid);
return;
}
resp.response = r_success;
memset(resp.error_text, '\0', sizeof(resp.error_text));
save_errno = 0;
switch(resp.request) {
case s_create_new_database:
if (!database initialize(1))
resp.response = r_failure;
break;
case s_get_cdc_entry:
resp.cdc_entry_data =
get_cdc_entry(comm.cdc_entry_data.catalog);
break;
case s_get_cdt_entry:
resp.cdt_entry_data =
get_cdt_entry(comm.cdt_entry_data.catalog,
comm.cdt_entry_data.track_no);
break;
case s_add_cdc_entry:
if (!add_cdc_entry(comm.cdc_entry_data))
resp.response = r_failure;
break;
case s_add_cdt_entry:
if (!add_cdt_entry(comm.cdt_entry_data))
resp.response = r_failure;
break;
case s_del_cdc_entry:
if (!del_cdc_entry(comm.cdc_entry_data.catalog))
resp.response = r_failure;
break;
case s_del_cdt_entry:
if (!del_cdt_entry(comm.cdt_entry_data.catalog,
comm.cdt_entry_data.track_no)) resp.response = r_failure;
break;
case s_find_cdc_entry:
do {
resp.cdc_entry_data =
search_cdc_entry(comm.cdc_entry_data.catalog, &first_time);
if (resp.cdc_entry_data.catalog[0] != 0) {
resp.response = r_success;
if (!send_resp_to_client(resp)) {
fprintf(stderr,
"Server Warning:- failed to respond to %d\n", resp.client_pid);
break;
}
} else {
resp.response = r_find_no_more;
}
} while (resp.response == r_success);
break;
default:
resp.response = r_failure;
break;
} /* switch */
sprintf(resp.error_text,
"Command failed:\n\t%s\n", strerror(save_errno));
if (!send_resp_to_client(resp)) {
fprintf(stderr,
"Server Warning:- failed to respond to %d\n", resp.client_pid);
}
end_resp_to_client;
return;
}
Прежде чем рассматривать действующую реализацию канала, давайте обсудим последовательность событий, которые должны произойти для передачи данных между клиентским и серверным процессами. На рис. 13.9 показан запуск обоих, и клиентского, и серверного, процессов, а также то, как они образуют петлю во время обработки команд и ответов.
В этой реализации ситуация немного сложнее, т.к. в запросе на поиск клиент передает серверу одну команду и затем ждет один или несколько ответов от сервера. Это усложняет программу, особенно клиентскую часть.
Рис. 13.9
Канал
Далее показан файл реализации канала pipe_imp.с, в котором содержатся клиентские и серверные функции.