Untitled
unknown
c_cpp
a year ago
11 kB
5
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