Untitled

mail@pastecode.io avatar
unknown
c_cpp
2 months ago
11 kB
2
Indexable
Never
#include<iostream>
#include<winsock2.h>
#pragma comment (lib, "ws2_32.lib")// - директив, позволяющий избавиться от предупреждений, выдаваемых на стандартные библиотеки
#include<windows.h>// - так как работа с windows
#include<WinSock2.h>// - заголовочный файл для работы с сокетами
#include<WS2tcpip.h>// - дополнительный заголовок, так как работа с tcp/ip протоколами

#define WIN32_LEAN_AND_MEAN //- макрос, необходимый в случае с сетевыми вещами

using namespace std;

int main() {
	WSADATA wsaData;
	ADDRINFO hints; //- hints(подсказки)
	ADDRINFO* addrResult = NULL; // - указатель на addrinfo
	SOCKET ClientSocket = INVALID_SOCKET; // - переменная типа socket(инициализируем invalid, так как сейчас он еще не создан, а значит неверный) 
	SOCKET ListenSocket = INVALID_SOCKET;


	int result;
	const char* sendBuffer = "Hello from server!";
	char recvBuffer[512]; // - буфер для приема
	result = WSAStartup(MAKEWORD(2, 2), &wsaData);  // MAKEWORD - макрос
													//WSAStartup - функция для загрузки бибилиотек
	if (result != 0) // так как функция WSASrartup возвращает 0
	{
		cout << "WSAStartup failed, result = " << result << endl;
		return 1; // если main возвращает не 0, значит что программа отработала с ошибкой, 1 - код ошибки
	}

	ZeroMemory(&hints, sizeof(hints)); // ZeroMemory - заполняет блок памяти нулями
									   //&hints - указатель на память
									   //sizeof - оператор, позволяющий определить длину зануляемой памяти
	hints.ai_family = AF_INET;       // - то, какие протоколы будут использоваться
	hints.ai_socktype = SOCK_STREAM; // - тип сокета(в данном случае потоковый сокет)
	hints.ai_protocol = IPPROTO_TCP; // - используемый протокол
	hints.ai_flags = AI_PASSIVE;     // - получение информации для пассивной стороны(клиент - активная сторона; сервер - пассивная)



	result = getaddrinfo(NULL, "666", &hints, &addrResult); // - проверяет наличие удаленного узла в сети(строит к нему путь), создает одну или несколько структур адресов сокета
														    // 1 параметр - серверу неизвестно, какой клиент к нему подключается, значит неизвестен и адрес(адреса нет)														    // второй параметр - порт, на котором слушается соединение
														    // 2 параметр - порт(цифровой идентификатор программы)
															// 3, 4 параметры  - указатели на структуру addrinfo
														    // &addrResult содержит набор возможных сокетов, соединений, которые можно установить(распределился)
	if (result != 0)
	{
		cout << "Getaddrinfo failed with error: " << result << endl;
		WSACleanup(); // - деинициализация WSAStartup
		return 1;
	}

	ListenSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol);           //- создание сокета
																											  //- фунция возвращает номер сокет-дескриптора
																											  // 1 параметр - константа, семейство протоколов(лежит в addrResult)
																											  // 2 параметр - тип протокола(лежит в ai_socktype)
																											  // 3 параметр - то, какой мы используем протокол(лежит в ai_protocolif (ConnectSocket == INVALID_SOCKET) // - проверка создания сокета(если не создался
	if (ListenSocket == INVALID_SOCKET)
	{
		cout << "Socket creation  failed" << endl;
		WSACleanup();
		return 1;
	}

	result = bind(ListenSocket, addrResult->ai_addr, (int)addrResult->ai_addrlen);    // - используется для привязки к сокету адреса
																					  // 1 параметр - используемый сокет   
																					  // 2 параметр - указатель на адрес сервера
																					  // 3 параметр - длина сткуртуры адреса(целое число) 

	if (result == SOCKET_ERROR) // - проверка соединения с другой стороной(соединение не получилось)
	{
		cout << "Binding socket failed" << endl;
		closesocket(ListenSocket); // - закрываем сокет
		ListenSocket = INVALID_SOCKET;
		freeaddrinfo(addrResult); // - освобождение памяти после распределения
		WSACleanup();
		return 1; // - так как не удалось соединиться
	}
	result = listen(ListenSocket, SOMAXCONN); // - используется сервером, чтобы информировать ОС о том, что он ожидает("слушает") запросы связи на данном сокете
	                                          // 1 параметр - сокет для прослушивания
	                                          // 2 параметр - целое положительное число, определяющее как много запросов связи может быть принято на сокет одновременно
	                                          // - SOMAXCONN(константа, максимальное кол-во соединений, которое может обслужить сервер)

	if (result == SOCKET_ERROR)
	{
		cout << "Listening socket failed" << endl;
		closesocket(ListenSocket);
		freeaddrinfo(addrResult);
		WSACleanup();
		return 1;
	}

	ClientSocket = accept(ListenSocket, NULL, NULL );// - возвращает сокет, полученынный при соединении с клиентом
		                                             // 1 параметр - 
		                                             //2 парметр - указатель на адрес клиента( 0, так как сервер не интересуется адресом клиента)
		                                             // 3 параметр - указатель на длину структуры адреса( так же 0)


	if (ClientSocket == INVALID_SOCKET) // - операция завершилась неправильно
	{
		cout << "Accepting socket failed" << endl;
		closesocket(ListenSocket);
		freeaddrinfo(addrResult);
		WSACleanup();
		return 1;;
	}

	closesocket(ListenSocket); // - закрытие слушающего сокета(так как других клиентов не ждем), дальше работа только с клиентским

	do {                             // - прием данных до тех пор, пока не будет прервано соединение
		ZeroMemory(recvBuffer, 512); // - обнуление буфера

		result = recv(ClientSocket, recvBuffer, 512, 0);  // - используется для чтения данных из сокета(получение информации из клиентского сокета)
														  // 1 параметр - сокет
														  // 2 параметр - буфер, куда принимаем данные
														  // 3 параметр - размер буфера(указывать максимальный)
		if (result > 0)                               // - в успешном случае
		{
			cout << "Received " << result << " bytes " << endl; // - сколько данных полученно
			cout << "Received data:  " << recvBuffer << endl;   // - какие именно данные получены

			result = send(ClientSocket, sendBuffer, (int)strlen(sendBuffer), 0); // - оправляем свои данные клиенту
				                                                                // 1 параметр - кому отправляем данные
				                                                                // 2 параметр - буфер, откуда берутся данные
				                                                                // 3 параметр - длина отправляемых данных(отправляемая строка)
				                                                                // 4 параметр - флаги(если флаг = 0, то запись и считывание производится в порядке поступления байт))
		
			if (result == SOCKET_ERROR)  // - ошибка отправки данных обратно
			{
				cout << "Failed to send data back" << endl;
				closesocket(ClientSocket);
				freeaddrinfo(addrResult);
				WSACleanup();
				return 1;

		    }
		}

        else if (result == 0)
		{
			cout << "Connection closed" << endl;       // - отсутствие записанных в сокет даных
		}
		else if (result < 0)                           // - в случае ошибки
		{
			cout << "Recv failed with error" << endl;
			closesocket(ClientSocket);
			freeaddrinfo(addrResult);
			WSACleanup();
			return 1;
		}
	} while (result > 0);

	result = shutdown(ClientSocket, SD_SEND);  // - завершение программы
		                                      // 1 параметр - сокет
		                                      // 2 параметр - каким образом выключить(SD_SEND - любые передачи запрещены, но прием доступен) 
		if (result == SOCKET_ERROR) 
		{
			cout << "Shutdown client socket failed" << endl;
			closesocket(ClientSocket);
			freeaddrinfo(addrResult);
			WSACleanup();
			return 1;
	    }
	closesocket(ClientSocket);   // - в случае успешной работы программы
	freeaddrinfo(addrResult);
	WSACleanup();
	return 0;


}
Leave a Comment