Untitled
unknown
c_cpp
2 years ago
11 kB
8
Indexable
#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;
}Editor is loading...
Leave a Comment