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)); } }