Files
CS-LABS/mine/lab_4/vlad's/fifo_server.c
2025-12-10 16:50:28 +07:00

188 lines
5.9 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.
// fifo_server.c - Серверная программа с использованием именованных каналов (FIFO)
// Вариант повышенной сложности для Lab 4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
#define FIFO_REQUEST "/tmp/fifo_request"
#define FIFO_RESPONSE "/tmp/fifo_response"
#define BUFFER_SIZE 4096
volatile sig_atomic_t running = 1;
void signal_handler(int sig) {
(void)sig;
running = 0;
}
static long long parse_ll(const char *s) {
char *end = NULL;
errno = 0;
long long v = strtoll(s, &end, 10);
if (errno != 0 || end == s || *end != '\0' || v < 0) {
return -1;
}
return v;
}
long long process_data(const char *input, size_t input_len, char *output,
size_t output_size, long long max_replacements) {
long long total_replacements = 0;
size_t out_pos = 0;
size_t i = 0;
while (i < input_len && out_pos < output_size - 1) {
unsigned char c = (unsigned char)input[i];
/* Try to form a non-overlapping pair with the next character.
Do not treat newline as part of a pair (preserve line structure). */
if (i + 1 < input_len) {
unsigned char next = (unsigned char)input[i + 1];
if (c != '\n' && next != '\n' && c == next && total_replacements < max_replacements) {
/* write first char of pair */
output[out_pos++] = (char)c;
if (out_pos >= output_size - 1) break;
/* write space instead of second char */
output[out_pos++] = ' ';
total_replacements++;
i += 2; /* skip both chars (non-overlapping) */
continue;
}
}
/* No valid pair -> write current char */
output[out_pos++] = (char)c;
i++;
}
/* If we stopped early but still have room, copy remaining bytes (without forming pairs)
until output buffer full or input ends. This preserves trailing data. */
while (i < input_len && out_pos < output_size - 1) {
output[out_pos++] = input[i++];
}
output[out_pos] = '\0';
return total_replacements;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <max_replacements>\n", argv[0]);
return 1;
}
long long max_replacements = parse_ll(argv[1]);
if (max_replacements < 0) {
fprintf(stderr, "ERROR: Invalid max_replacements\n");
return 1;
}
printf("=== FIFO Server запущен ===\n");
printf("Server PID: %d\n", getpid());
printf("Максимум замен: %lld\n", max_replacements);
// Устанавливаем обработчик сигналов
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
// Удаляем старые FIFO, если существуют
unlink(FIFO_REQUEST);
unlink(FIFO_RESPONSE);
// Создаем именованные каналы
if (mkfifo(FIFO_REQUEST, 0666) == -1) {
perror("mkfifo request");
return 1;
}
if (mkfifo(FIFO_RESPONSE, 0666) == -1) {
perror("mkfifo response");
unlink(FIFO_REQUEST);
return 1;
}
printf("FIFO каналы созданы:\n");
printf(" Request: %s\n", FIFO_REQUEST);
printf(" Response: %s\n", FIFO_RESPONSE);
printf("Ожидание запросов от клиентов...\n\n");
while (running) {
// Открываем FIFO для чтения запроса
int fd_req = open(FIFO_REQUEST, O_RDONLY);
if (fd_req == -1) {
if (errno == EINTR) continue;
perror("open request FIFO");
break;
}
// Читаем данные от клиента
char *input_buffer = malloc(BUFFER_SIZE);
char *output_buffer = malloc(BUFFER_SIZE);
if (!input_buffer || !output_buffer) {
fprintf(stderr, "ERROR: Memory allocation failed\n");
close(fd_req);
free(input_buffer);
free(output_buffer);
continue;
}
ssize_t bytes_read = read(fd_req, input_buffer, BUFFER_SIZE - 1);
close(fd_req);
if (bytes_read <= 0) {
free(input_buffer);
free(output_buffer);
continue;
}
input_buffer[bytes_read] = '\0';
printf("Получен запрос: %zd байт\n", bytes_read);
// Обрабатываем данные
long long replacements = process_data(input_buffer, bytes_read,
output_buffer, BUFFER_SIZE,
max_replacements);
printf("Выполнено замен: %lld\n", replacements);
// Открываем FIFO для отправки ответа
int fd_resp = open(FIFO_RESPONSE, O_WRONLY);
if (fd_resp == -1) {
perror("open response FIFO");
free(input_buffer);
free(output_buffer);
continue;
}
// Отправляем обработанные данные
size_t output_len = strlen(output_buffer);
ssize_t bytes_written = write(fd_resp, output_buffer, output_len);
// Отправляем количество замен (в отдельной строке)
char result[64];
snprintf(result, sizeof(result), "\nREPLACEMENTS:%lld\n", replacements);
write(fd_resp, result, strlen(result));
close(fd_resp);
printf("Отправлен ответ: %zd байт\n\n", bytes_written);
free(input_buffer);
free(output_buffer);
}
// Очистка
printf("\nЗавершение работы сервера...\n");
unlink(FIFO_REQUEST);
unlink(FIFO_RESPONSE);
return 0;
}