Files
CS-LABS/mine/lab_4/fifo_client.c
2025-12-10 16:50:28 +07:00

156 lines
7.2 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.
#include <stdio.h> // printf, fprintf
#include <stdlib.h> // malloc, free, exit
#include <string.h> // strlen, strerror, strstr, sscanf
#include <unistd.h> // read, write, close, getpid
#include <fcntl.h> // open, O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC
#include <sys/types.h> // типы для системных вызовов
#include <sys/stat.h> // константы прав доступа (S_IRUSR и т.п.)
#include <errno.h> // errno и коды ошибок [web:17]
#define FIFO_REQUEST "/tmp/fifo_request" // путь к FIFO для запроса клиент→сервер
#define FIFO_RESPONSE "/tmp/fifo_response" // путь к FIFO для ответа сервер→клиент
#define BUFFER_SIZE 4096 // размер буфера для обмена данными
// Печать подсказки по использованию программы
void print_usage(const char *progname) {
fprintf(stderr, "Usage: %s <input_file> <output_file>\n", progname);
fprintf(stderr, "Example: %s input.txt output.txt\n", progname);
}
int main(int argc, char *argv[]) {
// Проверка числа аргументов командной строки
if (argc != 3) {
fprintf(stderr, "ERROR: Неверное количество аргументов\n");
print_usage(argv[0]);
return 1;
}
// Имена входного и выходного файлов берём из аргументов
const char *input_file = argv[1];
const char *output_file = argv[2];
// Информационное сообщение о запуске клиента
printf("=== FIFO Client ===\n");
printf("Client PID: %d\n", getpid());
printf("Входной файл: %s\n", input_file);
printf("Выходной файл: %s\n", output_file);
// Открываем входной файл для чтения
int in_fd = open(input_file, O_RDONLY);
if (in_fd < 0) {
fprintf(stderr, "ERROR: Не удалось открыть входной файл %s: %s\n",
input_file, strerror(errno));
return 1;
}
// Выделяем буфер под содержимое файла и обмен с сервером
char *buffer = malloc(BUFFER_SIZE);
if (!buffer) {
fprintf(stderr, "ERROR: Не удалось выделить память\n");
close(in_fd);
return 1;
}
// Читаем данные из входного файла (не более BUFFER_SIZE-1, оставляем место под '\0')
ssize_t bytes_read = read(in_fd, buffer, BUFFER_SIZE - 1);
close(in_fd);
if (bytes_read < 0) {
fprintf(stderr, "ERROR: Не удалось прочитать файл: %s\n", strerror(errno));
free(buffer);
return 1;
}
// Делаем буфер временно C-строкой для отладочного вывода
buffer[bytes_read] = '\0';
printf("Прочитано байт из файла: %zd\n", bytes_read);
// Открываем FIFO запроса на запись (ожидается, что сервер уже создал FIFO и слушает)
printf("Отправка запроса серверу...\n");
int fd_req = open(FIFO_REQUEST, O_WRONLY);
if (fd_req == -1) {
fprintf(stderr, "ERROR: Не удалось открыть FIFO запроса: %s\n", strerror(errno));
fprintf(stderr, "Убедитесь, что сервер запущен!\n");
free(buffer);
return 1;
}
// Отправляем прочитанные из файла данные серверу по FIFO запроса
ssize_t bytes_written = write(fd_req, buffer, bytes_read);
close(fd_req);
if (bytes_written != bytes_read) {
fprintf(stderr, "ERROR: Ошибка отправки данных\n");
free(buffer);
return 1;
}
printf("Отправлено байт: %zd\n", bytes_written);
// Открываем FIFO ответа на чтение, чтобы получить обработанные данные от сервера
printf("Ожидание ответа от сервера...\n");
int fd_resp = open(FIFO_RESPONSE, O_RDONLY);
if (fd_resp == -1) {
fprintf(stderr, "ERROR: Не удалось открыть FIFO ответа: %s\n", strerror(errno));
free(buffer);
return 1;
}
// Читаем ответ сервера в тот же буфер
ssize_t response_bytes = read(fd_resp, buffer, BUFFER_SIZE - 1);
close(fd_resp);
if (response_bytes < 0) {
fprintf(stderr, "ERROR: Ошибка чтения ответа\n");
free(buffer);
return 1;
}
// Делает ответ строкой для поиска служебной части с количеством замен
buffer[response_bytes] = '\0';
printf("Получено байт от сервера: %zd\n", response_bytes);
// В протоколе ответа сервер дописывает в конец строку вида "\nREPLACEMENTS:<число>"
// Ищем начало этой служебной информации
char *replacements_info = strstr(buffer, "\nREPLACEMENTS:");
long long replacements = 0;
if (replacements_info) {
// Считываем количество замен из служебной части
sscanf(replacements_info, "\nREPLACEMENTS:%lld", &replacements);
// Обрезаем строку в месте начала служебной части, оставляя только полезные данные
*replacements_info = '\0';
// Пересчитываем длину полезных данных как количество байт до служебного блока
response_bytes = replacements_info - buffer;
}
// Открываем (или создаём) выходной файл с правами rw-rw-rw-
int out_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (out_fd < 0) {
fprintf(stderr, "ERROR: Не удалось открыть выходной файл %s: %s\n",
output_file, strerror(errno));
free(buffer);
return 1;
}
// Записываем в выходной файл только содержимое (без служебной части REPLACEMENTS)
ssize_t written = write(out_fd, buffer, response_bytes);
close(out_fd);
if (written != response_bytes) {
fprintf(stderr, "ERROR: Ошибка записи в выходной файл\n");
free(buffer);
return 1;
}
// Информационные сообщения об успешной обработке
printf("Записано байт в выходной файл: %zd\n", written);
printf("Количество выполненных замен: %lld\n", replacements);
printf("\nОбработка завершена успешно!\n");
// Освобождение выделенной памяти и нормальное завершение
free(buffer);
return 0;
}