6-vlad untested
This commit is contained in:
210
lab_6/vlad/server.c
Normal file
210
lab_6/vlad/server.c
Normal file
@@ -0,0 +1,210 @@
|
||||
// server.c
|
||||
// Сервер POSIX IPC: разделяемая память + именованные семафоры. [file:21]
|
||||
// Задача: во всех парах одинаковых соседних символов второй символ заменить на пробел. [file:22]
|
||||
|
||||
#include <stdio.h> // printf, fprintf, perror, FILE, fopen, fclose, fprintf
|
||||
#include <stdlib.h> // exit, EXIT_FAILURE, strtoul
|
||||
#include <string.h> // memset, strncpy, strlen
|
||||
#include <errno.h> // errno
|
||||
#include <fcntl.h> // O_CREAT, O_EXCL, O_RDWR
|
||||
#include <sys/mman.h> // shm_open, mmap, munmap
|
||||
#include <sys/stat.h> // S_IRUSR, S_IWUSR
|
||||
#include <semaphore.h> // sem_t, sem_open, sem_close, sem_unlink, sem_wait, sem_post
|
||||
#include <unistd.h> // ftruncate, close
|
||||
|
||||
#define SHM_BUFFER_SIZE 1024 // Максимальный размер строки в shared memory. [file:21]
|
||||
|
||||
// Структура разделяемой памяти. [file:21]
|
||||
typedef struct {
|
||||
int has_data; // 1, если клиент записал строку. [file:21]
|
||||
int result_code; // 0 - успех, -1 - ошибка. [file:21]
|
||||
char buffer[SHM_BUFFER_SIZE]; // Буфер для строки. [file:21]
|
||||
} shared_block_t;
|
||||
|
||||
// Обработка строки по новому заданию: [file:22]
|
||||
// "Во всех парах одинаковых символов второй символ заменить на пробел".
|
||||
static void process_line(char *s) {
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; s[i] != '\0'; ++i) {
|
||||
// Идём по всей строке. [file:22]
|
||||
if (s[i] != '\0' && s[i + 1] != '\0' && s[i] == s[i + 1]) {
|
||||
// Если два соседних символа равны, второй заменяем на пробел. [file:22]
|
||||
s[i + 1] = ' ';
|
||||
// Можно сдвинуться дальше, чтобы не склеивать новые пары искусственно. [file:22]
|
||||
// Но по условию достаточно просто заменить второй символ.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// argv[1] - имя shm, argv[2] - имя sem_client, argv[3] - имя sem_server, argv[4] - итерации. [file:22]
|
||||
if (argc < 4) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s <shm_name> <sem_client_name> <sem_server_name> [iterations]\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];
|
||||
|
||||
int iterations = -1; // -1 = работать до сигнала/внешнего завершения. [file:22]
|
||||
if (argc >= 5) {
|
||||
char *endptr = NULL;
|
||||
unsigned long tmp = strtoul(argv[4], &endptr, 10);
|
||||
if (endptr == argv[4] || *endptr != '\0') {
|
||||
fprintf(stderr, "Invalid iterations value: '%s'\n", argv[4]);
|
||||
return -1;
|
||||
}
|
||||
iterations = (int) tmp;
|
||||
}
|
||||
|
||||
// Простая зачистка возможных старых IPC-объектов. [file:21]
|
||||
shm_unlink(shm_name);
|
||||
sem_unlink(sem_client_name);
|
||||
sem_unlink(sem_server_name);
|
||||
|
||||
// Создаём shared memory. [file:21]
|
||||
int shm_fd = shm_open(shm_name,
|
||||
O_CREAT | O_EXCL | O_RDWR,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (shm_fd == -1) {
|
||||
perror("shm_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ftruncate(shm_fd, sizeof(shared_block_t)) == -1) {
|
||||
perror("ftruncate");
|
||||
close(shm_fd);
|
||||
shm_unlink(shm_name);
|
||||
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);
|
||||
shm_unlink(shm_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(shm_fd) == -1) {
|
||||
perror("close");
|
||||
}
|
||||
|
||||
// Инициализация shared memory. [file:21]
|
||||
shm_ptr->has_data = 0;
|
||||
shm_ptr->result_code = 0;
|
||||
memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer));
|
||||
|
||||
// Создаём семафоры. [file:21]
|
||||
sem_t *sem_client = sem_open(sem_client_name,
|
||||
O_CREAT | O_EXCL,
|
||||
S_IRUSR | S_IWUSR,
|
||||
0);
|
||||
if (sem_client == SEM_FAILED) {
|
||||
perror("sem_open(sem_client)");
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
shm_unlink(shm_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sem_t *sem_server = sem_open(sem_server_name,
|
||||
O_CREAT | O_EXCL,
|
||||
S_IRUSR | S_IWUSR,
|
||||
0);
|
||||
if (sem_server == SEM_FAILED) {
|
||||
perror("sem_open(sem_server)");
|
||||
sem_close(sem_client);
|
||||
sem_unlink(sem_client_name);
|
||||
munmap(shm_ptr, sizeof(shared_block_t));
|
||||
shm_unlink(shm_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Открываем файл вывода. [file:22]
|
||||
FILE *fout = fopen("output.txt", "w");
|
||||
if (!fout) {
|
||||
perror("fopen(output.txt)");
|
||||
// Продолжаем работать только через shared memory. [file:21]
|
||||
}
|
||||
|
||||
int processed_count = 0; // Сколько строк обработано. [file:22]
|
||||
|
||||
while (iterations < 0 || processed_count < iterations) {
|
||||
// Ждём строку от клиента. [file:21]
|
||||
if (sem_wait(sem_client) == -1) {
|
||||
perror("sem_wait(sem_client)");
|
||||
processed_count = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!shm_ptr->has_data) {
|
||||
fprintf(stderr, "Warning: sem_client posted, but has_data == 0\n");
|
||||
shm_ptr->result_code = -1;
|
||||
} else {
|
||||
// Обрабатываем строку по новому заданию. [file:22]
|
||||
process_line(shm_ptr->buffer);
|
||||
|
||||
shm_ptr->result_code = 0;
|
||||
shm_ptr->has_data = 0;
|
||||
processed_count++;
|
||||
|
||||
if (fout) {
|
||||
fprintf(fout, "%s\n", shm_ptr->buffer);
|
||||
fflush(fout);
|
||||
}
|
||||
}
|
||||
|
||||
// Сообщаем клиенту, что результат готов. [file:21]
|
||||
if (sem_post(sem_server) == -1) {
|
||||
perror("sem_post(sem_server)");
|
||||
processed_count = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fout && fclose(fout) == EOF) {
|
||||
perror("fclose(output.txt)");
|
||||
}
|
||||
|
||||
// Выводим число операций или -1. [file:22]
|
||||
if (processed_count >= 0) {
|
||||
printf("%d\n", processed_count);
|
||||
} else {
|
||||
printf("-1\n");
|
||||
}
|
||||
|
||||
// Очистка IPC-объектов. [file:21]
|
||||
if (sem_close(sem_client) == -1) {
|
||||
perror("sem_close(sem_client)");
|
||||
}
|
||||
if (sem_close(sem_server) == -1) {
|
||||
perror("sem_close(sem_server)");
|
||||
}
|
||||
|
||||
if (sem_unlink(sem_client_name) == -1) {
|
||||
perror("sem_unlink(sem_client)");
|
||||
}
|
||||
if (sem_unlink(sem_server_name) == -1) {
|
||||
perror("sem_unlink(sem_server)");
|
||||
}
|
||||
|
||||
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
|
||||
perror("munmap");
|
||||
}
|
||||
if (shm_unlink(shm_name) == -1) {
|
||||
perror("shm_unlink");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user