148 lines
4.4 KiB
C
148 lines
4.4 KiB
C
// client.c
|
||
// Клиент: читает строки из input.txt, передаёт их серверу через shared memory,
|
||
// ожидает обработку и печатает результат на stdout. [file:21][file:22]
|
||
|
||
#include <stdio.h> // printf, fprintf, perror, FILE, fopen, fclose, fgets
|
||
#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 <sys/stat.h> // mode_t
|
||
#include <semaphore.h> // sem_t, sem_open, sem_close, sem_wait, sem_post
|
||
#include <unistd.h> // close
|
||
|
||
#define SHM_BUFFER_SIZE 1024 // Должен совпадать с server.c. [file:21]
|
||
|
||
typedef struct {
|
||
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[]) {
|
||
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];
|
||
|
||
// Открываем существующий shm. [file:21]
|
||
int shm_fd = shm_open(shm_name, O_RDWR, 0);
|
||
if (shm_fd == -1) {
|
||
perror("shm_open");
|
||
return -1;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
if (close(shm_fd) == -1) {
|
||
perror("close");
|
||
}
|
||
|
||
// Открываем семафоры. [file:21]
|
||
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;
|
||
}
|
||
|
||
// Открываем input.txt. [file:22]
|
||
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;
|
||
|
||
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;
|
||
}
|
||
|
||
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)");
|
||
}
|
||
|
||
if (sem_close(sem_client) == -1) {
|
||
perror("sem_close(sem_client)");
|
||
}
|
||
if (sem_close(sem_server) == -1) {
|
||
perror("sem_close(sem_server)");
|
||
}
|
||
|
||
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
|
||
perror("munmap");
|
||
}
|
||
|
||
return 0;
|
||
}
|