• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Пишем "PedoChat" на С++

Dido

HDD-drive
Пользователь
Регистрация
06.01.2021
Сообщения
35
Реакции
34
Чтобы начать пилить этот чат, нам понадобится:
  1. Желание
  2. VS-2019 (студия)
  3. WS2tcpip.h (библиотека для winsocks, качать не надо, она уже «вмонтирована»)
  4. Прямые руки
  5. Программа Putty Скачать
  6. Свободного времени 1 час (с перерывами на сижку)
  7. Кофе (по желанию Пиво)
  8. Защита от пагубного влияния ретроградного Меркурия, если не помогло – см. пункт 1
Для начала давайте немного пробежимся по основным понятием и вспомогательным интерфейсам. WinSock - по сути, это «инструмент»\интерфейс, который входит в главную API WINDOWS библиотеку дабы упразднить разработку ПО на базе TCP\IP протоколов. То есть, можно смело сказать, что это интерфейс (если вы знакомы с ООП методологией, то это слова не должны отождествлять с GUI интерфейсом) к семейству протоколов TCP/IP. Представьте старую игру, когда группа двух ребят берет в руки вафельные стаканчики и протягивает между ними нитку, якобы для «прослушивания» друг друга на расстоянии. Так вот, стаканчики это и есть сокеты. На двух разных концах будут присутствовать «клиент» и «сервер», которые «общаются\взаимодействуют» между друг другом. Технология далеко не новая. Конечно, сами программисты windows не придумали их с нуля, их реализация лежит в основе «UNIX» систем еще интерфейса Беркли.

Проект будем реализовывать на основе двух разных проектах – первая часть сервак, вторая часть клиент. Все функции и детальный разбора я делать не буду, для этого нет времени, за то есть доп. ссылки и книги, которые я прикреплю. Для пущего понимая, я полагаю вы знакомы, что такое TCP/IP, ООП, функции и их вызов, структуры (С++).

Литература
UNIX сетевые?
C++ сетевое?
TCP/IP стек?

И так поехали

Часть 1 - Сервер
Создаем клиент-часть подключения_LI.jpg


создание первого файла_LI.jpg


Для начала мы подключаем препроцессорную директиву «WS2tcpip.h» для работы с winsocks. Самая главная функция для реализации winsocks это WSAStartup(принимает два параметра 1 – Версия, которая будет использоваться, 2 – указатель на адрес памяти структуры WSADATA). Остальные коменты написаны сразу в коде.
C++:
#include <iostream>
#include <WS2tcpip.h> // сокеты windows API для доступа к сетевым сокетам, будем работать через них. К тому
// же он включает функции для запила winsock и много других фу-й, которые мы будем юзать в ходе разработки
#pragma comment(lib, "ws2_32.lib")

using namespace std; // да-да знаю, bad practice, но учитывая что это дом. работа, упустим излишества


void main()
{
    setlocale(LC_ALL, "Russian");

    WSAData WinSockObj;  // структура для создания winsocks
    WORD version = MAKEWORD(2, 2); // версия winsocks, которые мы будем использовать
    int winSock = WSAStartup(version, &WinSockObj);  // передаем в ф-ю версию нашего винсокса и адрес самого obj winsocks
    if (winSock != 0)
    {
        cerr << "Программа не может создать winsock!" << endl; // думаю по циклу ясно, а поток выбрали конечно соответственный для ошибок
        return;
    }

    SOCKET listenSockServer = socket(AF_INET, SOCK_STREAM, 0); // версия inet  - IPV4 , используем поток сокет, а последнее значение просто ноль.
    if (listenSockServer == INVALID_SOCKET)  // +- тоже самое, что в предыдущем ветвлении, только отличает второй операнд на сравнение
        {
        cerr << "Программа не может создать сокет!" << endl;
        return;
        }


    sockaddr_in addressIPForSocket; // создаем на основе структуры объект на основе выбранного протокола
    int serverSizeAddr = sizeof(addressIPForSocket);
    addressIPForSocket.sin_family = AF_INET; // семейство inet - IPV4
    addressIPForSocket.sin_port = htons(40000); // способ передачи байтов от хоста к сети, номер порта рандом - главное, чтобы он у вас бы не занят какой то службой
    addressIPForSocket.sin_addr.S_un.S_addr = INADDR_ANY;


    bind(listenSockServer, (sockaddr*)&addressIPForSocket, serverSizeAddr); // связываем наш сокет с портом, указатель на адрес и размер структуры адреса
    listen(listenSockServer, SOMAXCONN); // начинаем чекать сокет на прослушку порта, SOMAXCONN максимальная длина очереди, которая прослушивает порт.
    

    sockaddr_in addrClient;                 // начинаем ожидать первых подключений
    int clientSizeAddr = sizeof(addrClient); // получаем размер адреса клиента
    SOCKET clientSocket = accept(listenSockServer, (sockaddr*)&addrClient, &clientSizeAddr); // слушаем, получаем адрес, порт по которому клиент может приконектиться
    if (clientSocket == INVALID_SOCKET)
    {
        cerr << "Программе не удалось подключить клиента по данному порту!" << endl;
    }


    char host[NI_MAXHOST]; // для получение имени клиента, который приконектился
    char service[NI_MAXHOST]; // порт по которому клиент приконектился
    ZeroMemory(host, NI_MAXHOST); // default заполняет память нулями, первый параметр это указатель на блок памяти, который нужно заполнить, а второй размер в байтах этой же памяти
    ZeroMemory(service, NI_MAXSERV);
    // getnameinfo это ф-ю которая преобра. адрес сокета в независимый хост\службу, притом похерестично на каком протоколе это базируется.
    if (getnameinfo((sockaddr*)&clientSocket, clientSizeAddr, host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) // одним словом, если коннект удался...
    {
        cout << host << "  Удачно подключился по порту " << service << endl;
    }
    else
    {
        inet_ntop(AF_INET, &addrClient.sin_addr, host, NI_MAXHOST);
        cout << host << " подключение по порту " << htons(addrClient.sin_port) << endl;
    }
    closesocket(listenSockServer);

    char bufferSize[10000]; // размер буфера, делайте какой захотите сами
    while (true) // ожидаем клиента, пока он не отправит какие либо данные
    {
        ZeroMemory(bufferSize, 10000);
        int dataReceived = recv(clientSocket, bufferSize, 10000, 0); // ф-ю для отправки данных
        if (dataReceived == SOCKET_ERROR)
        {
            cerr << "Программа словила ошибку в отправке данных" << endl;
            break;
        }
        if (dataReceived == 0) // если ничего не получили, значить клиент вышел
        {
            cout << "Клиент покинул чат" << endl;
            break;
        }
        cout << string(bufferSize, 0, dataReceived) << endl;
        send(clientSocket, bufferSize, dataReceived + 1, 0); // сообщение для отправки клиенту, размер n+1 для нулевого символа
    }
    closesocket(clientSocket);
    WSACleanup(); // закрываем нашу лавочку и очищаем winsock
    // Закрываем сокет
    // Выключаем сокет
}
Написали, проверили код, делаем компиляцию
запускаем сервер_LI.jpg


Теперь включаем Putty
используем putty для connecta_LI (2).jpg



putty дропнулся, но коннект произошел_LI.jpg


Часть 2 - Клиент
Снова проделываем те же махинации по созданию проекта, как и предыдущем случае.
Создаем клиент-часть подключения_LI.jpg


Делаем main() func для клиента
создаем главную функцию для клиента_LI.jpg


C++:
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")

using namespace std;

void main ()
{
    setlocale(LC_ALL, "Russian");
    string ipAddressServer = "127.0.0.1"; // IP адрес сервака по какому будем конектиться
    int portServer = 40000; // Порт для прослушки на сервере
    WSADATA WinSocksObjClient;
    WORD version = MAKEWORD(2, 2);
    int winSocksResultConnect = WSAStartup(version, &WinSocksObjClient); // переменная для запуска нашего winsocks
    if (winSocksResultConnect != 0) // проверяем, смогли ли получить коннект
    {
        cerr << "Программа не может создать winsock! " << winSocksResultConnect << endl;
        return;
    }
    SOCKET listenSockClient = socket(AF_INET, SOCK_STREAM, 0);
    if (listenSockClient == INVALID_SOCKET)
    {
        cerr << "Программа не может создать сокет, " << WSAGetLastError() << endl; // вызываем метод выдачи ошибок
    }
    sockaddr_in addressIPForClientSocket; // проделываем те же махинации, как и со структурой сокета сервера
    addressIPForClientSocket.sin_family = AF_INET;
    addressIPForClientSocket.sin_port = htons(portServer); // передаем переме. номера порта
    int sizeOfaddressIPForClientSocket = sizeof(addressIPForClientSocket); // перем. для хранения размера структуры
    inet_pton(AF_INET, ipAddressServer.c_str(), &addressIPForClientSocket.sin_addr);

    int connectResultToServer = connect(listenSockClient, (sockaddr*)&addressIPForClientSocket, sizeOfaddressIPForClientSocket); // реализуем коннект к серверу
    if (connectResultToServer == SOCKET_ERROR) // проверяем подключение
    {
        cerr << "Программа не может подключиться к серверу" << WSAGetLastError() << endl;
        closesocket(listenSockClient); // закрываем и очищаем
        WSACleanup();
        return;
    }
    char bufferSize[10000];
    string dataFromClient;
    do
    {
        cout << " ||>.. "; // приглашаешь к вводу данных
        getline(cin, dataFromClient); // по средства ф-и getline получаем поток ввода и данные от клиента
        if (dataFromClient.size() > 0) // чекнем, чтобы юзер что то отправил сперва
        {
            int sendResultFromClient = send(listenSockClient, dataFromClient.c_str(), dataFromClient.size() + 1, 0); // переменная для хранения результата отправки данных от клиента
            if (sendResultFromClient != SOCKET_ERROR)
            {
                ZeroMemory(bufferSize, 10000);
                int bytesReceivedFromCLient = recv(listenSockClient, bufferSize, 10000, 0); // фу-я для получение данных от клиента
                if (bytesReceivedFromCLient > 0)
                {
                    cout << "Сервер говорит: " << string(bufferSize, 0, bytesReceivedFromCLient) << endl; // выводим все в консоль
                }
            }
        }
    } while (dataFromClient.size() > 0);
    closesocket(listenSockClient);
    WSACleanup();
}
успешная компиляция клиента _LI.jpg


Теперь добавляем для удобства запуска серверную часть
кликаем правой кнопкой на наше решение и добавляем наш Сервер проект .png


сервер добавили тоже в проект.png

Проверяем, правильно ли добавили все файлы. Теперь выбираем свойства нашего решения
снова выбираем свойства нашего решения.png


и выставляем приоритет загрузки наших проектов.png


И теперь запускаете F5 и ловите пруфы от своего чата.
если вы проделали все верно, то мои вам поздравления -  вы кампухтер мастер lvl 90+_LI.jpg
 
Пожалуйста, обратите внимание, что пользователь заблокирован
почему PEDO чат? Что это значит

Товарищ майор, тут дела нет, просто неправильно выразился молодой человек. Никакой педофилии, выдыхайте, и займитесь делом, наконец.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
ТС, поменьше скринов, побольше текста. Коменты в коде, со стороны, это заметки для самого себя, мол я так вижу.. ИМХО
Пиши еще, развивайся
 
ТС, поменьше скринов, побольше текста. Коменты в коде, со стороны, это заметки для самого себя, мол я так вижу.. ИМХО
Пиши еще, развивайся
замечание принято, исправимся, спасибо. Думал наоборот, вроде как, больше скринов, меньше текста(кроме кода и коментов), но вижу подход выбрал не верный.
 
Чтобы начать пилить этот чат, нам понадобится:
  1. Желание
  2. VS-2019 (студия)
  3. WS2tcpip.h (библиотека для winsocks, качать не надо, она уже «вмонтирована»)
  4. Прямые руки
  5. Программа Putty Скачать
  6. Свободного времени 1 час (с перерывами на сижку)
  7. Кофе (по желанию Пиво)
  8. Защита от пагубного влияния ретроградного Меркурия, если не помогло – см. пункт 1
Для начала давайте немного пробежимся по основным понятием и вспомогательным интерфейсам. WinSock - по сути, это «инструмент»\интерфейс, который входит в главную API WINDOWS библиотеку дабы упразднить разработку ПО на базе TCP\IP протоколов. То есть, можно смело сказать, что это интерфейс (если вы знакомы с ООП методологией, то это слова не должны отождествлять с GUI интерфейсом) к семейству протоколов TCP/IP. Представьте старую игру, когда группа двух ребят берет в руки вафельные стаканчики и протягивает между ними нитку, якобы для «прослушивания» друг друга на расстоянии. Так вот, стаканчики это и есть сокеты. На двух разных концах будут присутствовать «клиент» и «сервер», которые «общаются\взаимодействуют» между друг другом. Технология далеко не новая. Конечно, сами программисты windows не придумали их с нуля, их реализация лежит в основе «UNIX» систем еще интерфейса Беркли.

Проект будем реализовывать на основе двух разных проектах – первая часть сервак, вторая часть клиент. Все функции и детальный разбора я делать не буду, для этого нет времени, за то есть доп. ссылки и книги, которые я прикреплю. Для пущего понимая, я полагаю вы знакомы, что такое TCP/IP, ООП, функции и их вызов, структуры (С++).

Литература
UNIX сетевые?
C++ сетевое?
TCP/IP стек?

И так поехали

Часть 1 - Сервер
Посмотреть вложение 28401

Посмотреть вложение 28404

Для начала мы подключаем препроцессорную директиву «WS2tcpip.h» для работы с winsocks. Самая главная функция для реализации winsocks это WSAStartup(принимает два параметра 1 – Версия, которая будет использоваться, 2 – указатель на адрес памяти структуры WSADATA). Остальные коменты написаны сразу в коде.
C++:
#include <iostream>
#include <WS2tcpip.h> // сокеты windows API для доступа к сетевым сокетам, будем работать через них. К тому
// же он включает функции для запила winsock и много других фу-й, которые мы будем юзать в ходе разработки
#pragma comment(lib, "ws2_32.lib")

using namespace std; // да-да знаю, bad practice, но учитывая что это дом. работа, упустим излишества


void main()
{
    setlocale(LC_ALL, "Russian");

    WSAData WinSockObj;  // структура для создания winsocks
    WORD version = MAKEWORD(2, 2); // версия winsocks, которые мы будем использовать
    int winSock = WSAStartup(version, &WinSockObj);  // передаем в ф-ю версию нашего винсокса и адрес самого obj winsocks
    if (winSock != 0)
    {
        cerr << "Программа не может создать winsock!" << endl; // думаю по циклу ясно, а поток выбрали конечно соответственный для ошибок
        return;
    }

    SOCKET listenSockServer = socket(AF_INET, SOCK_STREAM, 0); // версия inet  - IPV4 , используем поток сокет, а последнее значение просто ноль.
    if (listenSockServer == INVALID_SOCKET)  // +- тоже самое, что в предыдущем ветвлении, только отличает второй операнд на сравнение
        {
        cerr << "Программа не может создать сокет!" << endl;
        return;
        }


    sockaddr_in addressIPForSocket; // создаем на основе структуры объект на основе выбранного протокола
    int serverSizeAddr = sizeof(addressIPForSocket);
    addressIPForSocket.sin_family = AF_INET; // семейство inet - IPV4
    addressIPForSocket.sin_port = htons(40000); // способ передачи байтов от хоста к сети, номер порта рандом - главное, чтобы он у вас бы не занят какой то службой
    addressIPForSocket.sin_addr.S_un.S_addr = INADDR_ANY;


    bind(listenSockServer, (sockaddr*)&addressIPForSocket, serverSizeAddr); // связываем наш сокет с портом, указатель на адрес и размер структуры адреса
    listen(listenSockServer, SOMAXCONN); // начинаем чекать сокет на прослушку порта, SOMAXCONN максимальная длина очереди, которая прослушивает порт.
    

    sockaddr_in addrClient;                 // начинаем ожидать первых подключений
    int clientSizeAddr = sizeof(addrClient); // получаем размер адреса клиента
    SOCKET clientSocket = accept(listenSockServer, (sockaddr*)&addrClient, &clientSizeAddr); // слушаем, получаем адрес, порт по которому клиент может приконектиться
    if (clientSocket == INVALID_SOCKET)
    {
        cerr << "Программе не удалось подключить клиента по данному порту!" << endl;
    }


    char host[NI_MAXHOST]; // для получение имени клиента, который приконектился
    char service[NI_MAXHOST]; // порт по которому клиент приконектился
    ZeroMemory(host, NI_MAXHOST); // default заполняет память нулями, первый параметр это указатель на блок памяти, который нужно заполнить, а второй размер в байтах этой же памяти
    ZeroMemory(service, NI_MAXSERV);
    // getnameinfo это ф-ю которая преобра. адрес сокета в независимый хост\службу, притом похерестично на каком протоколе это базируется.
    if (getnameinfo((sockaddr*)&clientSocket, clientSizeAddr, host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) // одним словом, если коннект удался...
    {
        cout << host << "  Удачно подключился по порту " << service << endl;
    }
    else
    {
        inet_ntop(AF_INET, &addrClient.sin_addr, host, NI_MAXHOST);
        cout << host << " подключение по порту " << htons(addrClient.sin_port) << endl;
    }
    closesocket(listenSockServer);

    char bufferSize[10000]; // размер буфера, делайте какой захотите сами
    while (true) // ожидаем клиента, пока он не отправит какие либо данные
    {
        ZeroMemory(bufferSize, 10000);
        int dataReceived = recv(clientSocket, bufferSize, 10000, 0); // ф-ю для отправки данных
        if (dataReceived == SOCKET_ERROR)
        {
            cerr << "Программа словила ошибку в отправке данных" << endl;
            break;
        }
        if (dataReceived == 0) // если ничего не получили, значить клиент вышел
        {
            cout << "Клиент покинул чат" << endl;
            break;
        }
        cout << string(bufferSize, 0, dataReceived) << endl;
        send(clientSocket, bufferSize, dataReceived + 1, 0); // сообщение для отправки клиенту, размер n+1 для нулевого символа
    }
    closesocket(clientSocket);
    WSACleanup(); // закрываем нашу лавочку и очищаем winsock
    // Закрываем сокет
    // Выключаем сокет
}
Написали, проверили код, делаем компиляцию
Посмотреть вложение 28407


Теперь включаем Putty
Посмотреть вложение 28408


Посмотреть вложение 28409

Часть 2 - Клиент
Снова проделываем те же махинации по созданию проекта, как и предыдущем случае.
Посмотреть вложение 28410


Делаем main() func для клиента
Посмотреть вложение 28411

C++:
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")

using namespace std;

void main ()
{
    setlocale(LC_ALL, "Russian");
    string ipAddressServer = "127.0.0.1"; // IP адрес сервака по какому будем конектиться
    int portServer = 40000; // Порт для прослушки на сервере
    WSADATA WinSocksObjClient;
    WORD version = MAKEWORD(2, 2);
    int winSocksResultConnect = WSAStartup(version, &WinSocksObjClient); // переменная для запуска нашего winsocks
    if (winSocksResultConnect != 0) // проверяем, смогли ли получить коннект
    {
        cerr << "Программа не может создать winsock! " << winSocksResultConnect << endl;
        return;
    }
    SOCKET listenSockClient = socket(AF_INET, SOCK_STREAM, 0);
    if (listenSockClient == INVALID_SOCKET)
    {
        cerr << "Программа не может создать сокет, " << WSAGetLastError() << endl; // вызываем метод выдачи ошибок
    }
    sockaddr_in addressIPForClientSocket; // проделываем те же махинации, как и со структурой сокета сервера
    addressIPForClientSocket.sin_family = AF_INET;
    addressIPForClientSocket.sin_port = htons(portServer); // передаем переме. номера порта
    int sizeOfaddressIPForClientSocket = sizeof(addressIPForClientSocket); // перем. для хранения размера структуры
    inet_pton(AF_INET, ipAddressServer.c_str(), &addressIPForClientSocket.sin_addr);

    int connectResultToServer = connect(listenSockClient, (sockaddr*)&addressIPForClientSocket, sizeOfaddressIPForClientSocket); // реализуем коннект к серверу
    if (connectResultToServer == SOCKET_ERROR) // проверяем подключение
    {
        cerr << "Программа не может подключиться к серверу" << WSAGetLastError() << endl;
        closesocket(listenSockClient); // закрываем и очищаем
        WSACleanup();
        return;
    }
    char bufferSize[10000];
    string dataFromClient;
    do
    {
        cout << " ||>.. "; // приглашаешь к вводу данных
        getline(cin, dataFromClient); // по средства ф-и getline получаем поток ввода и данные от клиента
        if (dataFromClient.size() > 0) // чекнем, чтобы юзер что то отправил сперва
        {
            int sendResultFromClient = send(listenSockClient, dataFromClient.c_str(), dataFromClient.size() + 1, 0); // переменная для хранения результата отправки данных от клиента
            if (sendResultFromClient != SOCKET_ERROR)
            {
                ZeroMemory(bufferSize, 10000);
                int bytesReceivedFromCLient = recv(listenSockClient, bufferSize, 10000, 0); // фу-я для получение данных от клиента
                if (bytesReceivedFromCLient > 0)
                {
                    cout << "Сервер говорит: " << string(bufferSize, 0, bytesReceivedFromCLient) << endl; // выводим все в консоль
                }
            }
        }
    } while (dataFromClient.size() > 0);
    closesocket(listenSockClient);
    WSACleanup();
}
Посмотреть вложение 28412

Теперь добавляем для удобства запуска серверную часть
Посмотреть вложение 28413

Посмотреть вложение 28414
Проверяем, правильно ли добавили все файлы. Теперь выбираем свойства нашего решения
Посмотреть вложение 28415

Посмотреть вложение 28416

И теперь запускаете F5 и ловите пруфы от своего чата.
Посмотреть вложение 28417
1636011025660.png
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх