Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

if (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 failed\n");

}

return(0);

 }

 read_bytes = read(server_fd, rec_ptr, sizeof(*rec_ptr));

}

if (read_bytes == sizeof(*rec_ptr)) return_code = 1;

Сервер —

это единственный процесс, способный одновременно обслуживать множество клиентов. Поскольку каждый клиент применяет свой канал для получения ответов, адресованных ему, сервер, для того чтобы отправить ответы разным клиентам, должен писать в разные каналы. Поскольку файловые дескрипторы — это ограниченный ресурс, сервер открывает клиентский канал для записи только тогда, когда у него есть данные для отправки.

В программном коде открытие клиентского канала, запись в него и закрытие канала разделены на три отдельные функции. Когда вы возвращаете многочисленные результаты поиска, такой подход необходим, для того чтобы можно было открыть канал один раз, записать в него множество ответов и затем снова закрыть канал.

Прокладка каналов

1. Сначала откройте канал клиента.

int start_resp_to_client(const message_db_t mess_to_send) {

#if DEBUG_TRACE

 printf("%d :- start_resp_to_client\n", getpid);

#endif

 (void)sprintf(client_pipe_name, CLIENT_PIPE,

mess_to_send.client_pid);

 if ((client_fd = open(client_pipe_name, O_WRONLY)) == -1) return(0);

 return(1);

}

2. Все сообщения отправляются с помощью данной функции. Соответствующие клиентские функции, которые принимают сообщение, вы увидите позже.

int send_resp_to_client(const message_db_t mess_to_send) {

 int write_bytes;

#if DEBUG_TRACE

 printf("%d :- send_resp_to_client\n", getpid);

#endif

 if (client_fd == -1) return(0);

 write_bytes = write(client_fd, &mess_to_send, sizeof(mess_to_send));

 if (write_bytes != sizeof(mess_to_send)) return(0);

 return(1);

}

3. В заключение закройте клиентский канал.

void end resp_to_client(void) {

#if DEBUG_TFACE

 printf("%d :- end_resp_to_client\n", getpid);

#endif

 if (client_fd != -1) {

(void)close(сlient_fd);

client_fd = -1;

 }

}

Функции на стороне клиента

Дополнение к серверу — клиентские функции в файле pipe_imp.c. Они очень похожи на серверные функции за исключением функции с интригующим именем

send_mess_to_server
.

Клиентские функции

1. После проверки доступности сервера

функция
client_starting
инициализирует канал клиентской стороны.

int client_starting(void) {

#if DEBUG_TFACE

 printf("%d client_starting\n", getpid);

#endif

 mypid = getpid;

 if ((server_fd = open(SERVER_PIPE, O_WRONLY)) == -1) {

fprintf(stderr, "Server not running\n");

return(0);

 }

 (void)sprintf(client pipe name, CLIENT_PIPE, mypid);

 (void)unlink(client_pipe_name);

 if (mkfifo(client_pipe_name, 0777) == -1) {

fprintf(stderr, "Unable to create client pipe %s\n", client_pipe_name);

return(0);

 }

 return(1);

}

2. Функция

client_ending
закрывает файловые дескрипторы и удаляет ненужный теперь именованный канал.

void client_ending(void) {

#if DEBUG_TRACE

 printf("%d client_ending\n", getpid);

#endif

 if (client_write_fd != -1) (void)close(client_write_fd);

 if (client_fd != -1) (void)close(client_fd);

 if (server_fd != -1) (void)close(server_fd);

 (void)unlink(client_pipe_name);

}

3. Функция

send_mess_to_server
передает запрос через канал сервера.

int send_mess_to_server(message_db_t mess_to_send) {

 int write_bytes;

#if DEBUG_TRACE

 printf("%d send_mess_to_server\n", getpid);

#endif

 if (server_fd == -1) return(0);

 mess_to_send.client_pid = mypid;

 write_bytes = write(server_fd, &mess_to_send, sizeof(mess_to_send));

 if (write_bytes != sizeof(mess_to_send)) return(0);

 return(1);

}

Как и в серверных функциях, клиент получает назад результаты от сервера с помощью трех функций, обслуживающих множественные результаты поисков.

Получение результатов с сервера

1. Данная клиентская функция запускается для ожидания ответа сервера. Она открывает канал клиента только для чтения и затем повторно открывает файл канала только для записи. Чуть позже в этом разделе вы поймете почему.

int start_resp_from_server(void) {

#if DEBUG_TRACE

 printf("%d :- start_resp_from_server\n", getpid);

#endif

 if (client_pipe_name[0] == '\0') return(0);

Поделиться с друзьями: