C++ СИСТЕМА ОБНОВЛЕНИЯ ПРИЛОЖЕНИЙ 2.0

 

СЕРВЕРНАЯ ЧАСТЬ

Здесь, в новой версии, добавлен функционал чтения файла config.txt, куда можно добавлять имена обновляемых программ. Это позволяет обойтись без перекомпиляции сервиса при обновлении списка.

#include <iostream> //библиотека ввода-вывода
#include <cstdlib> //библиотека для работы с системными функциями
#include <cstring> //библиотека для работы со строками
#include <unistd.h> //библиотека для работы с POSIX-совместимыми системами
#include <sys/socket.h> //библиотека для работы с сокетами
#include <netinet/in.h> //библиотека для работы с сетевыми адресами
#define PORT 6666 //номер порта

int main()
{
    while(true){
    int server_fd, new_socket; //дескрипторы сокетов
    struct sockaddr_in address; //структура для хранения адреса
    int opt = 1; //опция для сокета
    int addrlen = sizeof(address); //размер структуры адреса
    char buffer[128000]; //буфер для приема данных
    char aDrr[] = "/data/fileserver/"; //Переменная, где мы укажем путь сохранения прнимаемого файла
    char filename[256]; //имя файла
    char full_path[512];//Переменная, где мы укажем путь сохранения прнимаемого файла и его имя
    int bytes_received = 0; //количество принятых байт

    // Создание TCP-сокета
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    // Установка опции для сокета
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
                                                  &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }

    // Заполнение структуры адреса
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // Привязка сокета к адресу и порту
    if (bind(server_fd, (struct sockaddr *)&address,
                                 sizeof(address))<0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // Прослушивание порта
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    // Ожидание подключения клиента
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
                       (socklen_t*)&addrlen))<0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    // Прием сообщения с ключом $file
    bytes_received = recv(new_socket, buffer, sizeof(buffer), 0);
    if (bytes_received < 0) {
        perror("recv");
        exit(EXIT_FAILURE);
    }

    // Поиск имени файла в сообщении
    char* pos = strstr(buffer, "$file ");
    if (pos) {
        strcpy(filename, pos + 6); //копирование имени файла
        std::cout << "Filename: " << filename << std::endl;
    } else {
        std::cout << "Filename not found" << std::endl;
        exit(EXIT_FAILURE);
    }

    // Отправка ответа $Ok
    const char* response = "$Ok";
    if (send(new_socket, response, strlen(response), 0) < 0) {
        perror("send");
        exit(EXIT_FAILURE);
    }

    strcpy(full_path, aDrr); //Здесь мы копируем одну строку в другую в одну
    strcat(full_path, filename); //А здесь конкатенируем две строки в одну 

    // Открытие файла для записи
    FILE* fp = fopen(full_path, "wb");
    if (fp == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    // Прием фрагментов файла и запись в файл
    while ((bytes_received = recv(new_socket, buffer, sizeof(buffer), 0)) > 0) {
        fwrite(buffer, 1, bytes_received, fp);
    }
    std::cout << "File " << filename << " recieved!" << std::endl;
    // Закрытие файла и сокетов
    fclose(fp);
    close(new_socket);
    close(server_fd);
    // Очищаем буфур, чтобы в следующей итерации вместо имени файла не было всякого лишнего дерьма.
    memset(buffer, 0, sizeof(buffer));
	}
}