From 58f2fb3fe76c4b9fbebec4aec15a8dd71e771b95 Mon Sep 17 00:00:00 2001 From: pajjilykk Date: Thu, 11 Dec 2025 09:40:07 +0700 Subject: [PATCH] 8-mine commented --- mine/lab_8/client.c | 14 ++++++-- mine/lab_8/server.c | 83 +++++++++++++++++++++++---------------------- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/mine/lab_8/client.c b/mine/lab_8/client.c index 43da5b3..ff22fec 100644 --- a/mine/lab_8/client.c +++ b/mine/lab_8/client.c @@ -1,11 +1,11 @@ -// client_udp.c +// UDP‑клиент: читает файл и отправляет его содержимое серверу блоками UDP. #include #include #include #include #include -#include // inet_pton, sockaddr_in [web:74] +#include // inet_pton, sockaddr_in #include #include @@ -13,6 +13,7 @@ #define END_MARKER "END_OF_TRANSMISSION" int main(int argc, char *argv[]) { + // argv[1] — IP сервера, argv[2] — порт, argv[3] — входной файл. if (argc < 4) { fprintf(stderr, "Usage: %s \n", @@ -27,6 +28,7 @@ int main(int argc, char *argv[]) { const char *server_port = argv[2]; const char *input_path = argv[3]; + // Разбираем номер порта. char *endptr = NULL; errno = 0; long port_long = strtol(server_port, &endptr, 10); @@ -43,6 +45,7 @@ int main(int argc, char *argv[]) { return -1; } + // Создаём UDP‑сокет. int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); @@ -50,11 +53,13 @@ int main(int argc, char *argv[]) { return -1; } + // Заполняем адрес сервера: IPv4 + порт. struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); + // inet_pton конвертирует строку IP ("127.0.0.1") в бинарный вид. if (inet_pton(AF_INET, server_ip, &servaddr.sin_addr) != 1) { fprintf(stderr, "ERROR: invalid IP address '%s'\n", server_ip); close(sockfd); @@ -64,6 +69,7 @@ int main(int argc, char *argv[]) { char buf[BUF_SIZE]; + // Читаем файл блоками и каждый блок отправляем одной UDP‑датаграммой. for (;;) { size_t n = fread(buf, 1, sizeof(buf), fin); if (n > 0) { @@ -81,6 +87,7 @@ int main(int argc, char *argv[]) { } } + // Если прочитали меньше, чем размер буфера — это EOF или ошибка. if (n < sizeof(buf)) { if (ferror(fin)) { perror("fread"); @@ -88,7 +95,7 @@ int main(int argc, char *argv[]) { fclose(fin); return -1; } - break; + break; // EOF. } } @@ -96,6 +103,7 @@ int main(int argc, char *argv[]) { perror("fclose(input_file)"); } + // Отправляем серверу маркер конца передачи. ssize_t sent = sendto(sockfd, END_MARKER, strlen(END_MARKER), diff --git a/mine/lab_8/server.c b/mine/lab_8/server.c index bc18c26..bb75d73 100644 --- a/mine/lab_8/server.c +++ b/mine/lab_8/server.c @@ -1,40 +1,33 @@ -// server_udp.c -// Лабораторная №8, вариант (UDP, чётный номер): -// "Заменить на пробелы все символы, совпадающие с первым символом в строке, кроме первого". [file:22] -// Сервер UDP: принимает текстовые блоки от клиента, построчно обрабатывает и пишет в файл. [web:78] +// UDP‑сервер: принимает текст по сети, построчно обрабатывает и пишет в файл. -#include // printf, fprintf, perror, FILE, fopen, fclose, fgets -#include // exit, EXIT_FAILURE, strtoul -#include // memset, strlen, strchr, strcpy, strncpy -#include // errno -#include // close -#include // sockaddr_in, inet_ntoa, htons, htonl, ntohs, ntohl -#include // socket, bind, recvfrom, sendto -#include // типы сокетов +#include +#include +#include +#include +#include +#include // sockaddr_in, htons, htonl, ntohs, ntohl +#include // socket, bind, recvfrom +#include -#define BUF_SIZE 4096 // Размер сетевого буфера. [web:78] - -// Специальная строка для обозначения конца передачи. [web:81] +#define BUF_SIZE 4096 #define END_MARKER "END_OF_TRANSMISSION" -// Функция обработки одной строки по условию варианта. [file:22] -static void process_line(char *line, - long long *repl_counter) { +// Обработка одной строки по условию: заменяет на пробелы +// все символы, совпадающие с первым, кроме самого первого. +static void process_line(char *line, long long *repl_counter) { if (!line || !repl_counter) { - return; // Защита от некорректных указателей. [file:22] + return; } - size_t len = strlen(line); // Получаем длину строки. [file:73] + size_t len = strlen(line); if (len == 0) { - return; // Пустая строка не обрабатывается. [file:22] + return; } - char first = line[0]; // Первый символ строки – ключ для замен. [file:22] + char first = line[0]; - // Проходим по строке начиная со второго символа. [file:22] for (size_t i = 1; i < len; ++i) { if (line[i] == first && line[i] != '\n') { - // Заменяем совпадающий символ пробелом и увеличиваем счётчик. [file:22] line[i] = ' '; (*repl_counter)++; } @@ -42,9 +35,7 @@ static void process_line(char *line, } int main(int argc, char *argv[]) { - // Ожидаемые аргументы: - // argv[1] - порт UDP сервера (например, 5000). [web:78] - // argv[2] - имя выходного файла. [file:22] + // argv[1] — порт сервера UDP, argv[2] — выходной файл. if (argc < 3) { fprintf(stderr, "Usage: %s \n", @@ -55,7 +46,7 @@ int main(int argc, char *argv[]) { return -1; } - // Разбираем номер порта. [web:78] + // Разбор номера порта. char *endptr = NULL; errno = 0; long port_long = strtol(argv[1], &endptr, 10); @@ -66,7 +57,7 @@ int main(int argc, char *argv[]) { } int port = (int) port_long; - const char *out_path = argv[2]; // Имя выходного файла. [file:22] + const char *out_path = argv[2]; FILE *fout = fopen(out_path, "w"); if (!fout) { @@ -74,18 +65,20 @@ int main(int argc, char *argv[]) { return -1; } - int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Создаём UDP-сокет. [web:74] + // Создаём UDP‑сокет: AF_INET (IPv4), SOCK_DGRAM (UDP). + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); fclose(fout); return -1; } + // Заполняем адрес сервера и привязываем сокет к порту (bind). struct sockaddr_in servaddr; - memset(&servaddr, 0, sizeof(servaddr)); // Обнуляем структуру адреса. [web:74] - servaddr.sin_family = AF_INET; // IPv4. [web:74] - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // Принимать на всех интерфейсах. [web:74] - servaddr.sin_port = htons(port); // Порт сервера в сетевом порядке байт. [web:74] + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; // IPv4. + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // принимать на всех интерфейсах. + servaddr.sin_port = htons(port); // порт в сетевом порядке байт. if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { perror("bind"); @@ -97,40 +90,45 @@ int main(int argc, char *argv[]) { printf("UDP server is listening on port %d, output file: %s\n", port, out_path); - char buf[BUF_SIZE]; // Буфер для приёма UDP-пакетов. [web:78] - char line_buf[BUF_SIZE]; // Буфер для накопления текущей строки. [file:22] - size_t line_len = 0; // Текущая длина строки в line_buf. [file:22] - long long total_replacements = 0; // Общее количество замен. [file:22] + char buf[BUF_SIZE]; // сюда прилетают UDP‑датаграммы. + char line_buf[BUF_SIZE]; // здесь накапливаем одну логическую строку. + size_t line_len = 0; + long long total_replacements = 0; - int done = 0; // Флаг завершения при получении END_MARKER. [web:81] + int done = 0; // флаг завершения по END_MARKER. while (!done) { struct sockaddr_in cliaddr; socklen_t cli_len = sizeof(cliaddr); + + // recvfrom читает один UDP‑пакет и заполняет адрес отправителя. ssize_t n = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &cliaddr, - &cli_len); // Принимаем UDP-дейтаграмму. [web:74] + &cli_len); if (n < 0) { perror("recvfrom"); total_replacements = -1; break; } - buf[n] = '\0'; // Делаем строку ASCIIZ для удобства. [web:78] + buf[n] = '\0'; // удобнее работать как со строкой. + // Специальный маркер конца передачи от клиента. if (strcmp(buf, END_MARKER) == 0) { printf("Received END marker, finishing.\n"); done = 1; break; } + // Разбор принятого блока посимвольно, сборка полных строк по '\n'. size_t pos = 0; while (pos < (size_t) n) { char c = buf[pos++]; if (c == '\n') { + // Закончили строку в line_buf. line_buf[line_len] = '\0'; process_line(line_buf, &total_replacements); if (fprintf(fout, "%s\n", line_buf) < 0) { @@ -141,6 +139,7 @@ int main(int argc, char *argv[]) { } line_len = 0; } else { + // Продолжаем накапливать строку. if (line_len + 1 < sizeof(line_buf)) { line_buf[line_len++] = c; } else { @@ -151,6 +150,8 @@ int main(int argc, char *argv[]) { } } + // Если соединение завершилось не на границе строки — + // доробатываем последний неполный хвост в line_buf. if (line_len > 0 && total_replacements >= 0) { line_buf[line_len] = '\0'; process_line(line_buf, &total_replacements);