Загрузка данных
#include <windows.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <ctime>
using namespace std;
const char* PIPE_NAME = "\\\\.\\pipe\\PilgrimagePipe";
const int NUM_SHIPS = 2;
const int SHIP_CAPACITY = 5;
const int MIN_SAIL_TIME = 3000;
const int MAX_SAIL_TIME = 6000;
HANDLE mutexHandle;
HANDLE finishEvent;
LONG clientCounter = 0;
int totalPilgrims = 0;
int byShip = 0;
int onFoot = 0;
struct Ship
{
int id;
int passengers;
bool inPort;
int voyages;
HANDLE fullEvent;
};
Ship ships[NUM_SHIPS];
void print_time()
{
SYSTEMTIME lt;
GetLocalTime(<);
printf("%02d:%02d:%02d\t", lt.wHour, lt.wMinute, lt.wSecond);
}
int RandomRange(int left, int right)
{
return left + rand() % (right - left + 1);
}
DWORD WINAPI ShipThread(LPVOID lpParam)
{
Ship* ship = (Ship*)lpParam;
HANDLE waitHandles[2];
waitHandles[0] = ship->fullEvent;
waitHandles[1] = finishEvent;
while (true)
{
WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
WaitForSingleObject(mutexHandle, INFINITE);
bool finishSignaled = (WaitForSingleObject(finishEvent, 0) == WAIT_OBJECT_0);
if (finishSignaled && ship->passengers == 0)
{
ReleaseMutex(mutexHandle);
print_time();
cout << "[SHIP] Корабль #" << ship->id << " завершает работу.\n";
return 0;
}
if (ship->passengers == 0)
{
ResetEvent(ship->fullEvent);
ReleaseMutex(mutexHandle);
continue;
}
int currentPassengers = ship->passengers;
ship->inPort = false;
print_time();
if (finishSignaled && currentPassengers < SHIP_CAPACITY)
{
cout << "[SHIP] Корабль #" << ship->id
<< " выполняет последний рейс с "
<< currentPassengers << " паломниками.\n";
}
else
{
cout << "[SHIP] Корабль #" << ship->id
<< " заполнен (" << currentPassengers
<< " паломников) и отплывает.\n";
}
ReleaseMutex(mutexHandle);
Sleep(RandomRange(MIN_SAIL_TIME, MAX_SAIL_TIME));
WaitForSingleObject(mutexHandle, INFINITE);
ship->voyages++;
ship->passengers = 0;
ship->inPort = true;
ResetEvent(ship->fullEvent);
print_time();
cout << "[SHIP] Корабль #" << ship->id
<< " вернулся. Совершено рейсов: "
<< ship->voyages << ".\n";
ReleaseMutex(mutexHandle);
}
}
string processRequest(const string& request, LONG clientId)
{
stringstream ss(request);
int pilgrimId = 0;
int patienceMs = 0;
if (!(ss >> pilgrimId >> patienceMs))
{
return "ERROR invalid format";
}
string extra;
if (ss >> extra)
{
return "ERROR invalid format";
}
print_time();
cout << "[CLIENT] Клиент №" << clientId
<< " -> паломник #" << pilgrimId
<< " прибыл. Терпение: " << patienceMs << " мс.\n";
DWORD startTime = GetTickCount();
while (true)
{
bool boarded = false;
int shipId = 0;
int placeNumber = 0;
WaitForSingleObject(mutexHandle, INFINITE);
for (int i = 0; i < NUM_SHIPS; i++)
{
if (ships[i].inPort && ships[i].passengers < SHIP_CAPACITY)
{
ships[i].passengers++;
shipId = ships[i].id;
placeNumber = ships[i].passengers;
byShip++;
boarded = true;
print_time();
cout << "[CLIENT] Паломник #" << pilgrimId
<< " сел на корабль #" << shipId
<< ". Место " << placeNumber
<< "/" << SHIP_CAPACITY << ".\n";
if (ships[i].passengers == SHIP_CAPACITY)
{
SetEvent(ships[i].fullEvent);
}
break;
}
}
ReleaseMutex(mutexHandle);
if (boarded)
{
return "SHIP " + to_string(shipId) + " " + to_string(placeNumber);
}
DWORD waited = GetTickCount() - startTime;
if (waited >= (DWORD)patienceMs)
{
WaitForSingleObject(mutexHandle, INFINITE);
onFoot++;
print_time();
cout << "[CLIENT] Паломник #" << pilgrimId
<< " не дождался корабля и ушел пешком.\n";
ReleaseMutex(mutexHandle);
return "FOOT";
}
Sleep(100);
}
}
DWORD WINAPI ClientHandler(LPVOID lpParam)
{
HANDLE hPipe = (HANDLE)lpParam;
LONG clientId = InterlockedIncrement(&clientCounter);
print_time();
cout << "[SERVER] Клиент №" << clientId << " вошел в обработку.\n";
char buffer[256];
DWORD bytesRead = 0;
DWORD bytesWritten = 0;
BOOL readOk = ReadFile(
hPipe,
buffer,
sizeof(buffer) - 1,
&bytesRead,
NULL
);
if (!readOk || bytesRead == 0)
{
print_time();
cout << "[ERROR] Failed to read from client №" << clientId << ".\n";
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
return 1;
}
buffer[bytesRead] = '\0';
string request = buffer;
print_time();
cout << "[SERVER] Получено от клиента №" << clientId
<< ": " << request << endl;
string responseText = processRequest(request, clientId);
print_time();
cout << "[SERVER] Ответ клиенту №" << clientId
<< ": " << responseText << endl;
BOOL writeOk = WriteFile(
hPipe,
responseText.c_str(),
(DWORD)responseText.size(),
&bytesWritten,
NULL
);
if (!writeOk)
{
print_time();
cout << "[ERROR] Failed to write to client №" << clientId << ".\n";
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
return 1;
}
print_time();
cout << "[SERVER] Клиент №" << clientId << " вышел из обработки.\n";
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
return 0;
}
int main()
{
setlocale(LC_ALL, "Russian");
srand((unsigned)time(nullptr));
mutexHandle = CreateMutex(NULL, FALSE, NULL);
if (mutexHandle == NULL)
{
cout << "Failed to create mutex." << endl;
return 1;
}
finishEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (finishEvent == NULL)
{
cout << "Failed to create finish event." << endl;
return 1;
}
for (int i = 0; i < NUM_SHIPS; i++)
{
ships[i].id = i + 1;
ships[i].passengers = 0;
ships[i].inPort = true;
ships[i].voyages = 0;
ships[i].fullEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ships[i].fullEvent == NULL)
{
cout << "Failed to create ship event." << endl;
return 1;
}
}
HANDLE shipThreads[NUM_SHIPS];
for (int i = 0; i < NUM_SHIPS; i++)
{
shipThreads[i] = CreateThread(NULL, 0, ShipThread, &ships[i], 0, NULL);
if (shipThreads[i] == NULL)
{
cout << "Failed to create ship thread." << endl;
return 1;
}
}
cout << "Введите количество паломников: ";
cin >> totalPilgrims;
while (cin.fail() || totalPilgrims < 1 || totalPilgrims > 50 || cin.peek() != '\n')
{
cin.clear();
cin.ignore(32768, '\n');
cout << "Некорректный ввод. Введите количество паломников: ";
cin >> totalPilgrims;
}
cout << "Server is waiting for clients..." << endl;
vector<HANDLE> clientThreads;
for (int i = 0; i < totalPilgrims; i++)
{
HANDLE hPipe = CreateNamedPipeA(
PIPE_NAME,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
256,
256,
0,
NULL
);
if (hPipe == INVALID_HANDLE_VALUE)
{
cout << "Failed to create pipe." << endl;
continue;
}
cout << "Waiting for client #" << (i + 1) << "..." << endl;
BOOL connected = ConnectNamedPipe(hPipe, NULL) ?
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (!connected)
{
cout << "Failed to connect client." << endl;
CloseHandle(hPipe);
continue;
}
cout << "Client connected." << endl;
HANDLE hThread = CreateThread(
NULL,
0,
ClientHandler,
hPipe,
0,
NULL
);
if (hThread == NULL)
{
cout << "Failed to create thread." << endl;
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
continue;
}
clientThreads.push_back(hThread);
}
if (!clientThreads.empty())
{
WaitForMultipleObjects((DWORD)clientThreads.size(), clientThreads.data(), TRUE, INFINITE);
}
print_time();
cout << "[SERVER] Все паломники определились со способом пути.\n";
WaitForSingleObject(mutexHandle, INFINITE);
for (int i = 0; i < NUM_SHIPS; i++)
{
if (ships[i].passengers > 0)
{
SetEvent(ships[i].fullEvent);
}
}
ReleaseMutex(mutexHandle);
SetEvent(finishEvent);
for (int i = 0; i < NUM_SHIPS; i++)
{
SetEvent(ships[i].fullEvent);
}
WaitForMultipleObjects(NUM_SHIPS, shipThreads, TRUE, INFINITE);
cout << "\n========== ИТОГ ==========\n";
cout << "Всего паломников: " << totalPilgrims << endl;
cout << "Добрались кораблем: " << byShip << endl;
cout << "Ушли пешком: " << onFoot << endl;
for (int i = 0; i < NUM_SHIPS; i++)
{
cout << "Корабль #" << ships[i].id
<< " совершил рейсов: " << ships[i].voyages << endl;
}
cout << "==========================\n";
for (HANDLE h : clientThreads)
CloseHandle(h);
for (int i = 0; i < NUM_SHIPS; i++)
{
CloseHandle(shipThreads[i]);
CloseHandle(ships[i].fullEvent);
}
CloseHandle(finishEvent);
CloseHandle(mutexHandle);
return 0;
}