Files
CS-LABS/mine/lab_6/client.c
2025-12-11 09:11:32 +07:00

157 lines
5.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Клиент POSIX IPC: читает строки из input.txt, передаёт их серверу через
// POSIX shared memory и синхронизируется с сервером через именованные семафоры.
#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).
#define SHM_BUFFER_SIZE 1024
// Структура, находящаяся в POSIX shared memory.
typedef struct {
int has_data;
int result_code;
char buffer[SHM_BUFFER_SIZE];
} shared_block_t;
int main(int argc, char *argv[]) {
// 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]);
return -1;
}
const char *shm_name = argv[1];
const char *sem_client_name = argv[2];
const char *sem_server_name = argv[3];
// Открываем существующий объект POSIX shared memory, созданный сервером (shm_open).
int shm_fd = shm_open(shm_name, O_RDWR, 0);
if (shm_fd == -1) {
perror("shm_open");
return -1;
}
// Отображаем POSIX shared memory в адресное пространство клиента (mmap с MAP_SHARED).
shared_block_t *shm_ptr = mmap(NULL,
sizeof(shared_block_t),
PROT_READ | PROT_WRITE,
MAP_SHARED,
shm_fd,
0);
if (shm_ptr == MAP_FAILED) {
perror("mmap");
close(shm_fd);
return -1;
}
// После успешного mmap файловый дескриптор POSIX shared memory можно закрыть.
if (close(shm_fd) == -1) {
perror("close");
}
// Открываем именованные POSIX семафоры, которые создал сервер (sem_open).
sem_t *sem_client = sem_open(sem_client_name, 0);
if (sem_client == SEM_FAILED) {
perror("sem_open(sem_client)");
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
sem_t *sem_server = sem_open(sem_server_name, 0);
if (sem_server == SEM_FAILED) {
perror("sem_open(sem_server)");
sem_close(sem_client);
munmap(shm_ptr, sizeof(shared_block_t));
return -1;
}
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;
}
char input[SHM_BUFFER_SIZE];
while (fgets(input, sizeof(input), fin) != NULL) {
size_t len = strlen(input);
if (len > 0 && input[len - 1] == '\n') {
input[len - 1] = '\0';
}
memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer));
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_wait).
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;
}
// Клиент блокируется на семафоре сервера (sem_wait), пока сервер не закончит обработку.
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;
}
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;
}
printf("%s\n", shm_ptr->buffer);
}
if (fclose(fin) == EOF) {
perror("fclose(input.txt)");
}
// Закрываем дескрипторы POSIX семафоров в процессе клиента (sem_close).
if (sem_close(sem_client) == -1) {
perror("sem_close(sem_client)");
}
if (sem_close(sem_server) == -1) {
perror("sem_close(sem_server)");
}
// Отсоединяем отображённую область POSIX shared memory (munmap).
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
perror("munmap");
}
return 0;
}