Основы программирования в Linux
Основы программирования в Linux читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
if (!send_resp_to_client(resp)) { fprintf(stderr, "Server Warning:- failed to respond to %dn", resp.client_pid); } end_resp_to_client(); return;}Прежде чем рассматривать действующую реализацию канала, давайте обсудим последовательность событий, которые должны произойти для передачи данных между клиентским и серверным процессами. На рис. 13.9 показан запуск обоих, и клиентского, и серверного, процессов, а также то, как они образуют петлю во время обработки команд и ответов.
В этой реализации ситуация немного сложнее, т.к. в запросе на поиск клиент передает серверу одну команду и затем ждет один или несколько ответов от сервера. Это усложняет программу, особенно клиентскую часть.

Рис. 13.9
Канал
Далее показан файл реализации канала pipe_imp.с, в котором содержатся клиентские и серверные функции.
Как вы видели в главе 10, может быть определено символическое имя DEBUG_TRACE для того, чтобы показать последовательность вызовов, в которых клиентский и серверный процессы передают друг другу сообщения.
1. Прежде всего, директивы
#include#include "cd_data.h"#include "cliserv.h"2. Вы также определяете в файле программы несколько значений, нужных вам в разных функциях:
static int server_fd = -1;static pid_t mypid = 0;static char client_pipe_name[PATH_MAX + 1] = {' '};static int client_fd = -1;static int client_write_fd = -1;Далее нужно рассмотреть функции серверной стороны. В следующем разделе показаны функции, открывающие и закрывающие именованный канал и читающие сообщения от клиентов. В следующем за ним разделе приведен программный код, который открывает и закрывает клиентские каналы и пересылает по ним сообщения, основываясь на идентификаторе процесса, который клиент включает в свое сообщение.
1. Подпрограмма
server_startingopenreadint server_starting(void) {#if DEBUG_TRACE printf("%d server_starting()n", getpid());#endif unlink(SERVER_PIPE); if (mkfifo(SERVER_PIPE, 0777) == -1) { fprintf(stderr, "Server startup error, no FIFO createdn"); return(0); } if ((server_fd = open(SERVER_PIPE, O_RDONLY)) == -1) { if (errno == EINTR) return(0); fprintf(stderr, "Server startup error, no FIFO openedn"); return(0); } return(1);}2. Когда сервер завершает работу, он удаляет именованный канал, для того чтобы клиенты могли установить, что нет действующего сервера.
void server_ending(void) {#if DEBUG_TRACE printf("%d:- server_ending()n", getpid());#endif (void)close(server_fd); (void)unlink(SERVER_PIPE);}3. Функция
read_request_from_clientint read_request_from_client(message_db_t *rec_ptr) { int return_code = 0; int read_bytes;#if DEBUG_TRACE printf("%d :- read_request_from_client()n", getpid());#endif if (server_fd != -1) { read_bytes = read(server_fd, rec_ptr, sizeof(*rec_ptr)); ... } return(return_code);}4. В особом случае, когда ни у одного клиента нет канала, открытого для записи, вызов
readif (read_bytes == 0) { (void)close(server_fd); if ((server_fd = open(SERVER_PIPE, O_RDONLY)) == -1) { if (errno != EINTR) { fprintf(stderr, "Server error, FIFO open failedn"); } return(0); } read_bytes = read(server_fd, rec_ptr, sizeof(*rec_ptr));}if (read_bytes == sizeof(*rec_ptr)) return_code = 1;Сервер — это единственный процесс, способный одновременно обслуживать множество клиентов. Поскольку каждый клиент применяет свой канал для получения ответов, адресованных ему, сервер, для того чтобы отправить ответы разным клиентам, должен писать в разные каналы. Поскольку файловые дескрипторы — это ограниченный ресурс, сервер открывает клиентский канал для записи только тогда, когда у него есть данные для отправки.
