- •Задание на курсовую работу
- •Оглавление
- •Введение
- •Постановка задачи
- •1. Теоретические основы разрабатываемой системы
- •2. Описание алгоритма работы приложения
- •3. Описание структуры приложения
- •Основная функция клиента:
- •4. Результаты работы приложения
- •Заключение
- •Список использованной литературы
- •Приложение 1 Текст программы «server111.Cpp»
- •Основная функция сервера логирования:
- •Приложение 2 Текст программы «server222.Cpp»
- •Приложение 3 Текст программы «client.Cpp»
- •Приложение 4 Текст программы «log.Cpp»
- •Приложение 5 Текст программы «server1.Cpp»
- •Приложение 6 Текст программы «server2.Cpp»
- •Приложение 7 Текст программы «client.Cpp»
- •Приложение 8 Текст программы «clientOs.Cpp»
std::string getCurrentTime()
Возвращает текущее время в формате YYYY-MM-DD HH:MM:SS.
Используется для добавления временной метки к сообщениям в логе.
void writeLog(const std::string& message)
Записывает переданное сообщение в файл server.log с временной меткой.
Если файл не удается открыть, выводит сообщение об ошибке в консоль.
void handleServer(int clientSocket)
Обрабатывает сообщения, поступающие от серверов задач.
Принимает данные через сокет, записывает их в лог и завершает соединение, если сервер задач отключается.
int main()
Основная функция сервера логирования:
Создает сокет и привязывает его к порту 9000.
Запускает прослушивание входящих соединений.
Для каждого нового подключения создает поток, который вызывает handleServer.
4. Результаты работы приложения
Результаты работы приложения представлены на рисунках 1-9:
Рисунок 1 – Запуск сервера логирования
Рисунок 2 – Запуск сервера 1
Рисунок 3 – Запуск сервера 2
Рисунок 4 – Запуск клиента, подключение к серверу 1
Рисунок 5 – Запуск клиента, подключение к серверу 2
Рисунок 6 – Содержимое файла логов
Рисунок 7 – Запуск клиента на ОС windows
Рисунок 10 – Запуск клиента на ОС windows, подключение к серверу 1
Рисунок 11 – Запуск клиента на ОС windows, подключение к серверу 2
Рисунок 12 – Демонстрация работы разработанных приложений на двух устройствах
Заключение
В результате выполнения данной курсовой работы было успешно разработано многозадачное приложение, выполняющее получение, сбор и вывод системной информации, с применением технологии «клиент-сервер» в соответствии с индивидуальным вариантом задания. В ходе работы также были закреплены и углублены теоретические знания в области современных операционных систем, приобретены практические навыки разработки клиент-серверных приложений, использующих стандартные механизмы межпроцессного взаимодействия.
Список использованной литературы
1. Вдовикина Н.В., Машечкин И.В., Терехин А.Н., Томилин А.Н. «Операционные системы: взаимодействие процессов: учебно-методическое пособие». — Издательский отдел факультета ВМиК МГУ, 2008.
2. В.Г.Олифер, Н.А.Олифер. Сетевые операционные системы. – СПб.: Питер, 2009.
3. Э.Таненбаум. Современные операционные системы. 3-изд. – СПб.: Питер, 2011.
4. С.В. Назаров, А.И. Широков. «Современные операционные системы». — М., Бином, 2013.
5. Э.Таненбаум, Х.Бос. Современные операционные системы. 4-изд. – СПб.: Питер, 2015.
Приложение 1 Текст программы «server111.Cpp»
#include <arpa/inet.h>
#include <iostream>
#include <cstdio>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <sstream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <thread>
#include <ctime>
void sendLog(const std::string& message, const std::string& serverId) {
int logSocket = socket(AF_INET, SOCK_STREAM, 0);
if (logSocket < 0) {
std::cerr << "Error creating log socket" << std::endl;
return;
}
struct sockaddr_in logServerAddress;
logServerAddress.sin_family = AF_INET;
logServerAddress.sin_port = htons(9000); // Logging server port
inet_pton(AF_INET, "127.0.0.1", &logServerAddress.sin_addr); // Logging server IP
if (connect(logSocket, (struct sockaddr*)&logServerAddress, sizeof(logServerAddress)) < 0) {
std::cerr << "Error connecting to logging server" << std::endl;
close(logSocket);
return;
}
// Send server identifier
send(logSocket, serverId.c_str(), serverId.size(), 0);
// Send log message
send(logSocket, message.c_str(), message.size(), 0);
close(logSocket);
}
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
throw std::runtime_error("Failed to open pipe");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
int countDisks(const std::string& output) {
int count = 0;
std::istringstream stream(output);
std::string line;
// Skip the header
std::getline(stream, line);
// Count lines containing 'disk'
while (std::getline(stream, line)) {
if (line.find("disk") != std::string::npos) {
count++;
}
}
return count;
}
std::string getCurrentTime() {
time_t now = time(0);
char buffer[80];
struct tm tstruct;
localtime_r(&now, &tstruct); // Use localtime_r for thread safety
strftime(buffer, sizeof(buffer), "%Y-%m-%d %X", &tstruct);
return std::string(buffer);
}
void handleClient(int clientSocket, long numProcessors) {
sendLog("Client connected", "server1");
// Execute the command lsblk --nodeps to get disk and filesystem info
std::string output = exec("lsblk --nodeps");
// Count the number of hard disks
int diskCount = countDisks(output);
// Get the current time
std::string currentTime = getCurrentTime();
// Form the message for the client
std::string message = "Number of logical processors: " + std::to_string(numProcessors) + "\n" +
"Disk and filesystem information:\n" +
output +
"Number of hard disks: " + std::to_string(diskCount) + "\n" +
"Current time: " + currentTime + "\n";
// Send the response to the client
send(clientSocket, message.c_str(), message.size(), 0);
sendLog("Client request processed", "server1");
// Close the connection with the client
close(clientSocket);
std::cout << "Connection with the client closed." << std::endl;
sendLog("Connection with the client closed", "server1");
}
int main() {
sendLog("Server 1 started", "server1");
// Get the number of logical processors
long numProcessors = sysconf(_SC_NPROCESSORS_ONLN);
if (numProcessors == -1) {
std::cerr << "Error getting the number of logical processors." << std::endl;
sendLog("Error getting the number of logical processors", "server1");
return 1;
}
// Create a socket
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket < 0) {
std::cerr << "Error creating socket" << std::endl;
sendLog("Error creating socket", "server1");
return 1;
}
// Configure the server address
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY; // Accept connections on any address
serverAddress.sin_port = htons(8081); // Port 8081
// Bind the socket to the address
if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
std::cerr << "Error binding socket" << std::endl;
sendLog("Error binding socket", "server1");
close(serverSocket);
return 1;
}
// Start listening for incoming connections
if (listen(serverSocket, 5) < 0) {
std::cerr << "Error listening" << std::endl;
sendLog("Error listening", "server1");
close(serverSocket);
return 1;
}
std::cout << "Server started and waiting for connections on port 8081..." << std::endl;
// Main loop for handling clients
while (true) {
// Accept an incoming connection
int clientSocket = accept(serverSocket, nullptr, nullptr);
if (clientSocket < 0) {
std::cerr << "Error accepting connection" << std::endl;
sendLog("Error accepting connection", "server1");
continue; // Continue waiting for other clients
}
std::cout << "Client connected!" << std::endl;
// Create a new thread to handle the client
std::thread clientThread(handleClient, clientSocket, numProcessors);
clientThread.detach(); // Detach the thread to run independently
}
// Close the server socket (this will never happen in this case)
close(serverSocket);
return 0;
}
