6 seems to work
This commit is contained in:
161
lab_6/client.c
161
lab_6/client.c
@@ -1,40 +1,36 @@
|
||||
// client.c
|
||||
// Клиент POSIX IPC: подключается к существующей разделяемой памяти
|
||||
// и именованным семафорам, передаёт строку серверу и получает результат. [web:8]
|
||||
// Клиент POSIX IPC: читает строки из input.txt, передаёт их серверу через
|
||||
// разделяемую память и выводит обработанные строки на stdout. [file:21][web:57]
|
||||
|
||||
#include <stdio.h> // printf, fprintf, perror, fgets
|
||||
#include <stdio.h> // printf, fprintf, perror, FILE, fopen, fclose, fgets [web:60]
|
||||
#include <stdlib.h> // exit, EXIT_FAILURE
|
||||
#include <string.h> // memset, strncpy, strlen
|
||||
#include <errno.h> // errno
|
||||
#include <fcntl.h> // O_RDWR
|
||||
#include <sys/mman.h> // shm_open, mmap, munmap
|
||||
#include <fcntl.h> // O_RDWR [web:29]
|
||||
#include <sys/mman.h> // shm_open, mmap, munmap [web:47]
|
||||
#include <sys/stat.h> // mode_t
|
||||
#include <semaphore.h> // sem_t, sem_open, sem_close, sem_wait, sem_post
|
||||
#include <semaphore.h> // sem_t, sem_open, sem_close, sem_wait, sem_post [file:21]
|
||||
#include <unistd.h> // close
|
||||
|
||||
|
||||
// Максимальная длина строки для обмена (должна совпадать с сервером).
|
||||
// Размер буфера обмена (должен совпадать с server.c). [file:21]
|
||||
#define SHM_BUFFER_SIZE 1024
|
||||
|
||||
|
||||
// Структура данных в разделяемой памяти, та же, что и у сервера.
|
||||
// Та же структура, что и у сервера. [file:21]
|
||||
typedef struct {
|
||||
int has_data;
|
||||
int result_code;
|
||||
char buffer[SHM_BUFFER_SIZE];
|
||||
int has_data; // Флаг наличия данных от клиента. [file:21]
|
||||
int result_code; // Код результата обработки. [file:21]
|
||||
char buffer[SHM_BUFFER_SIZE]; // Буфер строки. [file:21]
|
||||
} shared_block_t;
|
||||
|
||||
|
||||
// Основная функция клиента.
|
||||
int main(int argc, char *argv[]) {
|
||||
// Ожидаем минимум три аргумента:
|
||||
// argv[1] - имя объекта shared memory (должно совпадать с сервером).
|
||||
// argv[2] - имя семафора клиента.
|
||||
// argv[3] - имя семафора сервера.
|
||||
// Ожидаемые аргументы:
|
||||
// argv[1] - имя shared memory (должно совпадать с сервером). [file:21]
|
||||
// argv[2] - имя семафора клиента. [file:21]
|
||||
// argv[3] - имя семафора сервера. [file:21]
|
||||
if (argc < 4) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <shm_name> <sem_client_name> <sem_server_name>\n",
|
||||
argv[0]);
|
||||
argv[0]); // Сообщаем о правильном формате запуска. [file:22]
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -42,14 +38,14 @@ int main(int argc, char *argv[]) {
|
||||
const char *sem_client_name = argv[2];
|
||||
const char *sem_server_name = argv[3];
|
||||
|
||||
// Открываем уже существующий объект разделяемой памяти. [web:8]
|
||||
// Открываем существующий объект shared memory, созданный сервером. [web:47]
|
||||
int shm_fd = shm_open(shm_name, O_RDWR, 0);
|
||||
if (shm_fd == -1) {
|
||||
perror("shm_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Отображаем его в адресное пространство процесса. [web:8]
|
||||
// Отображаем shared memory в адресное пространство клиента. [web:47]
|
||||
shared_block_t *shm_ptr = mmap(NULL,
|
||||
sizeof(shared_block_t),
|
||||
PROT_READ | PROT_WRITE,
|
||||
@@ -62,12 +58,12 @@ int main(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Дескриптор больше не нужен после mmap.
|
||||
// Дескриптор можно закрыть, mmap продолжает работать. [file:21]
|
||||
if (close(shm_fd) == -1) {
|
||||
perror("close");
|
||||
}
|
||||
|
||||
// Открываем существующие именованные семафоры. [web:16]
|
||||
// Открываем именованные семафоры, которые создал сервер. [file:21][web:40]
|
||||
sem_t *sem_client = sem_open(sem_client_name, 0);
|
||||
if (sem_client == SEM_FAILED) {
|
||||
perror("sem_open(sem_client)");
|
||||
@@ -83,75 +79,90 @@ int main(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Читаем строку из stdin.
|
||||
char input[SHM_BUFFER_SIZE];
|
||||
if (fgets(input, sizeof(input), stdin) == NULL) {
|
||||
// Ошибка чтения из stdin или EOF.
|
||||
fprintf(stderr, "No input line provided\n");
|
||||
// Открываем файл input.txt для чтения исходных строк. [web:57]
|
||||
FILE *fin = fopen("input.txt", "r");
|
||||
if (!fin) {
|
||||
perror("fopen(input.txt)");
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Удаляем перевод строки в конце, если он есть.
|
||||
size_t len = strlen(input);
|
||||
if (len > 0 && input[len - 1] == '\n') {
|
||||
input[len - 1] = '\0';
|
||||
char input[SHM_BUFFER_SIZE]; // Локальный буфер для чтения строки. [file:21]
|
||||
|
||||
// Читаем input.txt построчно до конца файла. [web:51]
|
||||
while (fgets(input, sizeof(input), fin) != NULL) {
|
||||
size_t len = strlen(input); // Длина считанной строки. [web:54]
|
||||
|
||||
// Удаляем конечный '\n', если он есть. [web:54]
|
||||
if (len > 0 && input[len - 1] == '\n') {
|
||||
input[len - 1] = '\0';
|
||||
}
|
||||
|
||||
// Очищаем буфер в shared memory перед записью новой строки. [file:21]
|
||||
memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer));
|
||||
|
||||
// Копируем строку из локального буфера в shared memory. [file:21]
|
||||
strncpy(shm_ptr->buffer, input, SHM_BUFFER_SIZE - 1);
|
||||
shm_ptr->buffer[SHM_BUFFER_SIZE - 1] = '\0';
|
||||
|
||||
// Устанавливаем флаг наличия данных для сервера. [file:21]
|
||||
shm_ptr->has_data = 1;
|
||||
|
||||
// Поднимаем семафор клиента, уведомляя сервер. [file:21][web:40]
|
||||
if (sem_post(sem_client) == -1) {
|
||||
perror("sem_post(sem_client)");
|
||||
fclose(fin);
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Ждём, пока сервер обработает строку. [file:21][web:40]
|
||||
if (sem_wait(sem_server) == -1) {
|
||||
perror("sem_wait(sem_server)");
|
||||
fclose(fin);
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Проверяем код результата, выставленный сервером. [file:21]
|
||||
if (shm_ptr->result_code != 0) {
|
||||
fprintf(stderr,
|
||||
"Server reported error, result_code = %d\n",
|
||||
shm_ptr->result_code);
|
||||
fclose(fin);
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Выводим обработанную строку на стандартный вывод. [file:22]
|
||||
printf("%s\n", shm_ptr->buffer);
|
||||
}
|
||||
|
||||
// Записываем строку в разделяемую память.
|
||||
// Сначала очищаем буфер.
|
||||
memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer));
|
||||
|
||||
// Копируем строку, гарантируя наличие '\0'.
|
||||
strncpy(shm_ptr->buffer, input, SHM_BUFFER_SIZE - 1);
|
||||
shm_ptr->buffer[SHM_BUFFER_SIZE - 1] = '\0';
|
||||
|
||||
// Устанавливаем флаг наличия данных.
|
||||
shm_ptr->has_data = 1;
|
||||
|
||||
// Передаём управление серверу: sem_post(sem_client). [web:16]
|
||||
if (sem_post(sem_client) == -1) {
|
||||
perror("sem_post(sem_client)");
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
// Закрываем input.txt после окончания чтения. [web:57]
|
||||
if (fclose(fin) == EOF) {
|
||||
perror("fclose(input.txt)");
|
||||
}
|
||||
|
||||
// Ждём завершения обработки: sem_wait(sem_server). [web:16]
|
||||
if (sem_wait(sem_server) == -1) {
|
||||
perror("sem_wait(sem_server)");
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Проверяем код результата, установленный сервером.
|
||||
if (shm_ptr->result_code != 0) {
|
||||
fprintf(stderr, "Server reported error, result_code = %d\n",
|
||||
shm_ptr->result_code);
|
||||
sem_close(sem_client);
|
||||
sem_close(sem_server);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Выводим обработанную строку на stdout.
|
||||
printf("%s\n", shm_ptr->buffer);
|
||||
|
||||
// Закрываем семафоры и отсоединяемся от разделяемой памяти. [web:8]
|
||||
// Закрываем семафоры. [file:21]
|
||||
if (sem_close(sem_client) == -1) {
|
||||
perror("sem_close(sem_client)");
|
||||
}
|
||||
if (sem_close(sem_server) == -1) {
|
||||
perror("sem_close(sem_server)");
|
||||
}
|
||||
|
||||
// Отсоединяем shared memory. [web:47]
|
||||
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
|
||||
perror("munmap");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0; // Нормальное завершение клиента. [file:22]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user