6-mie commented

This commit is contained in:
2025-12-11 09:11:32 +07:00
parent 6cd4088087
commit 71dfd554f8
2 changed files with 96 additions and 141 deletions

View File

@@ -1,36 +1,34 @@
// client.c
// Клиент POSIX IPC: читает строки из input.txt, передаёт их серверу через
// разделяемую память и выводит обработанные строки на stdout. [file:21][web:57]
// POSIX shared memory и синхронизируется с сервером через именованные семафоры.
#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 [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 [file:21]
#include <unistd.h> // close
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h> // shm_open, mmap, munmap — POSIX разделяемая память
#include <sys/stat.h>
#include <semaphore.h> // sem_open, sem_close, sem_wait, sem_post — POSIX семафоры
#include <unistd.h>
// Размер буфера обмена (должен совпадать с server.c). [file:21]
// Размер буфера обмена (должен совпадать с server.c).
#define SHM_BUFFER_SIZE 1024
// Та же структура, что и у сервера. [file:21]
// Структура, находящаяся в POSIX shared memory.
typedef struct {
int has_data; // Флаг наличия данных от клиента. [file:21]
int result_code; // Код результата обработки. [file:21]
char buffer[SHM_BUFFER_SIZE]; // Буфер строки. [file:21]
int has_data;
int result_code;
char buffer[SHM_BUFFER_SIZE];
} shared_block_t;
int main(int argc, char *argv[]) {
// Ожидаемые аргументы:
// argv[1] - имя shared memory (должно совпадать с сервером). [file:21]
// argv[2] - имя семафора клиента. [file:21]
// argv[3] - имя семафора сервера. [file:21]
// argv[1] - имя POSIX shared memory (должно совпадать с сервером).
// argv[2] - имя именованного семафора клиента.
// argv[3] - имя именованного семафора сервера.
if (argc < 4) {
fprintf(stderr,
"Usage: %s <shm_name> <sem_client_name> <sem_server_name>\n",
argv[0]); // Сообщаем о правильном формате запуска. [file:22]
argv[0]);
return -1;
}
@@ -38,14 +36,14 @@ int main(int argc, char *argv[]) {
const char *sem_client_name = argv[2];
const char *sem_server_name = argv[3];
// Открываем существующий объект shared memory, созданный сервером. [web:47]
// Открываем существующий объект POSIX shared memory, созданный сервером (shm_open).
int shm_fd = shm_open(shm_name, O_RDWR, 0);
if (shm_fd == -1) {
perror("shm_open");
return -1;
}
// Отображаем shared memory в адресное пространство клиента. [web:47]
// Отображаем POSIX shared memory в адресное пространство клиента (mmap с MAP_SHARED).
shared_block_t *shm_ptr = mmap(NULL,
sizeof(shared_block_t),
PROT_READ | PROT_WRITE,
@@ -58,12 +56,12 @@ int main(int argc, char *argv[]) {
return -1;
}
// Дескриптор можно закрыть, mmap продолжает работать. [file:21]
// После успешного mmap файловый дескриптор POSIX shared memory можно закрыть.
if (close(shm_fd) == -1) {
perror("close");
}
// Открываем именованные семафоры, которые создал сервер. [file:21][web:40]
// Открываем именованные POSIX семафоры, которые создал сервер (sem_open).
sem_t *sem_client = sem_open(sem_client_name, 0);
if (sem_client == SEM_FAILED) {
perror("sem_open(sem_client)");
@@ -79,7 +77,6 @@ int main(int argc, char *argv[]) {
return -1;
}
// Открываем файл input.txt для чтения исходных строк. [web:57]
FILE *fin = fopen("input.txt", "r");
if (!fin) {
perror("fopen(input.txt)");
@@ -89,28 +86,22 @@ int main(int argc, char *argv[]) {
return -1;
}
char input[SHM_BUFFER_SIZE]; // Локальный буфер для чтения строки. [file:21]
char input[SHM_BUFFER_SIZE];
// Читаем input.txt построчно до конца файла. [web:51]
while (fgets(input, sizeof(input), fin) != NULL) {
size_t len = strlen(input); // Длина считанной строки. [web:54]
size_t len = strlen(input);
// Удаляем конечный '\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]
// Клиент увеличивает семафор клиента (sem_post), разблокируя сервер (sem_wait).
if (sem_post(sem_client) == -1) {
perror("sem_post(sem_client)");
fclose(fin);
@@ -120,7 +111,7 @@ int main(int argc, char *argv[]) {
return -1;
}
// Ждём, пока сервер обработает строку. [file:21][web:40]
// Клиент блокируется на семафоре сервера (sem_wait), пока сервер не закончит обработку.
if (sem_wait(sem_server) == -1) {
perror("sem_wait(sem_server)");
fclose(fin);
@@ -130,7 +121,6 @@ int main(int argc, char *argv[]) {
return -1;
}
// Проверяем код результата, выставленный сервером. [file:21]
if (shm_ptr->result_code != 0) {
fprintf(stderr,
"Server reported error, result_code = %d\n",
@@ -142,16 +132,14 @@ int main(int argc, char *argv[]) {
return -1;
}
// Выводим обработанную строку на стандартный вывод. [file:22]
printf("%s\n", shm_ptr->buffer);
}
// Закрываем input.txt после окончания чтения. [web:57]
if (fclose(fin) == EOF) {
perror("fclose(input.txt)");
}
// Закрываем семафоры. [file:21]
// Закрываем дескрипторы POSIX семафоров в процессе клиента (sem_close).
if (sem_close(sem_client) == -1) {
perror("sem_close(sem_client)");
}
@@ -159,10 +147,10 @@ int main(int argc, char *argv[]) {
perror("sem_close(sem_server)");
}
// Отсоединяем shared memory. [web:47]
// Отсоединяем отображённую область POSIX shared memory (munmap).
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
perror("munmap");
}
return 0; // Нормальное завершение клиента. [file:22]
return 0;
}