Книга: Основы программирования в Linux

Пересмотр функций клиента

Пересмотр функций клиента

Теперь нужно внести изменения в клиентские функции.

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

int client starting() {
#if DEBUG_TRACE
 printf("%d :- client_startingn", getpid());
#endif
 serv_qid = msgget((key_t)SERVER_MQUEUE, 0666);
 if (serv_qid == -1) return(0);
 cli_qid = msgget((key_t)CLIENT_MQUEUE, 0666);
 if (cli_qid == -1) return(0);
 return(1);
}

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

void client_ending() {
#if DEBUG_TRACE
 printf("%d :- client_ending()n", getpid());
#endif
 serv_qid = -1;
 cli_qid = -1;
}

3. Для отправки сообщения серверу сохраните данные в своей структуре. Учтите, что вы должны задать ключ сообщения. Поскольку 0 — недопустимое значение для ключа, незаданный ключ означает, что он принимает (очевидно) случайное значение, поэтому иногда эта функция может возвращать ошибку, если значение оказывается нулевым.

int send_mess_to_server(message_db_t mess_to_send) {
 struct msg_passed my_msg;
#if DEBUG_TRACE
 printf("%d send_mess_to_server()n", getpid());
#endif
 my_msg.real_message = mess_to_send;
 my_msg.msg_key = mess_to_send.client_pid;
 if (msgsnd(serv_qid, (void *)&my_msg, sizeof(mess_to_send) , 0) == -1) {
  perror("Message send failed");
  return(0);
 }
 return(1);
}

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

int read_resp_from_server(message_db_t *rec_ptr) {
 struct msg_passed mymsg;
#if DEBUG_TRACE
 printf("%d :- read_resp_from_server()n", getpid());
#endif
 if (msgrcv(cli_qid, (void *)&my_msg, sizeof(*rec_ptr), getpid(), 0) == -1) {
  return(0);
 }
 *rec_ptr = my_msg.real_message;
 return(1);
}

5. Для сохранения совместимости с файлом pipe_imp.c необходимо объявить четыре дополнительные функции. Но в вашей программе они будут пустыми. Операции, которые они реализовывали в случае применения каналов, больше не нужны.

int start_resp_to_client(const message_db_t mess_to_send) {
 return(1);
}
void end_resp_to_client(void) {}
int start_resp_from_server(void) {
 return(1);
}
void end_resp_from_server(void) {}

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

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

Оглавление книги


Генерация: 0.290. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз