Re: Потоки

Thread Safe що це? Не можу знайти

22

Re: Потоки

https://uk.wikipedia.org/wiki/Багатониткова_безпека
В англійській версії є деталі, як її досягати.

23 Востаннє редагувалося Львовский сырник в мульти (26.01.2021 13:30:09)

Re: Потоки

const boost::system::error_code& що означає ось цей рядок? Бо на сайті він написаний в функції, але не використовується, мабудь.

24

Re: Потоки

Чекайте, може, колись на форумі зареєструється телепат і зможе вам відповісти.

Re: Потоки

#include <iostream>
#include <boost/asio.hpp>
#include <chrono>
#include <thread>

void printline(const boost::system::error_code&ercd)
{
    std::cout << "printline" << std::endl;
}

int main(void)
{
    /*boost::asio::io_context ioct;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(2000));
    std::cout << "ioct" << std::endl;
    sytr.wait();
    std::cout << "ioct" << std::endl;*/

    /*boost::asio::io_context ioct;
    std::cout << "ptl0" << std::endl;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(2500));
    sytr.wait();
    std::cout << "ptl1" << std::endl;
    sytr.async_wait(&printline);
    std::cout << "ptl2" << std::endl;
    ioct.run();*/
    /*boost::asio::io_context ioct;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(2500));
    std::cout << "ptl0" << std::endl;
    std::this_thread::sleep_for(std::chrono::microseconds(3000));
    std::cout << "ptl1" << std::endl;
    sytr.wait();
    std::cout << "ptl2" << std::endl;
    */
    boost::asio::io_context ioct;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(10000));
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    std::cout << "mainline" << std::endl;
    sytr.async_wait(&printline);
    std::cout << "mainline" << std::endl;
    ioct.run();
    std::cout << "кінець" << std::endl;
    return 0;
}

26 Востаннє редагувалося koala (26.01.2021 14:12:57)

Re: Потоки

І що ж саме у виразі

    /*boost::asio::io_context ioct;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(2000));
    std::cout << "ioct" << std::endl;
    sytr.wait();
    std::cout << "ioct" << std::endl;*/

    /*boost::asio::io_context ioct;
    std::cout << "ptl0" << std::endl;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(2500));
    sytr.wait();
    std::cout << "ptl1" << std::endl;
    sytr.async_wait(&printline);
    std::cout << "ptl2" << std::endl;
    ioct.run();*/
    void printline(const boost::system::error_code&ercd)
    /*boost::asio::io_context ioct;
    boost::asio::steady_timer sytr(ioct, boost::asio::chrono::milliseconds(2500));
    std::cout << "ptl0" << std::endl;
    std::this_thread::sleep_for(std::chrono::microseconds(3000));
    std::cout << "ptl1" << std::endl;
    sytr.wait();
    std::cout << "ptl2" << std::endl;
    */

вам незрозуміло? (трохи підредагував, викинув деякі зайві рядки)

Re: Потоки

Погортайте вище. Я питався про "const boost::system::error_code&". Без цього рядку не працює метод async_wait. На сайті він прописаний, але пояснення не надані. Тому й питаю нащо...
Ось https://www.boost.org/doc/libs/1_75_0/d … imer2.html

28

Re: Потоки

Якщо ви за вашим посиланням перейдете за steady_timer::async_wait(), то прочитаєте те, що вам треба.
П.С. Відповідь на ваше перше питання - проголошення змінної (або параметра функції) типу "посилання на константний boost::system::error_code".

Re: Потоки

Підкажіть хтось, будь ласка , як краще реалізувати функцію sendoneposmess, бо пів дня сиджу... Можливо можна якось мудріше реалізувати не можу знайти ынфлрмацыъ в інтернеті.
ось код сервера

#include <iostream>
#include <thread>
#include <WinSock2.h>
#include <string>

#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable : 4996)

struct person
{
    std::string name;
    int pass;
    person* next;
};


const int size = 10;
SOCKET massaccept[size];
std::thread massth[size];
person *massper;



void line(person** per, std::string nm, int passione)
{
    if ((*per) == nullptr)
    {
        (*per) = new person;
        (*per)->name = nm;
        (*per)->pass = passione;
        (*per)->next = nullptr;
    }
    else
    {
        if ((*per) != nullptr)
        {
            person* last = (*per);
            while (last->next != nullptr)
            {
                last = last->next;
            }
            last->next = new person;
            last = last->next;
            last->name = nm;
            last->pass = passione;
            last->next = nullptr;
        }
    }
    return;
}

bool findpass(person* fd)
{
    person* find = massper;
    while (find != nullptr)
    {
        if (find->name == fd->name && find->pass == fd->pass)
        {
            return true;
        }
        find = find->next;
    }
    return false;
}

int findname(std::string name)
{
    person* find = massper;
    int i = 0;
    while (find != nullptr)
    {
        if (find->name == name)
        {
            return i;
        }
        i = i + 1;
        find = find->next;
    }
    return -1;
}

enum option
{
    sendallmess,
    sendoneposmess,
    sendservermes,
    takemes,
    closesock,
    takeprivate
};

bool funcop(option op, int sock)
{
    switch (op)
    {
    case sendallmess:
    {
        char* mes = nullptr;
        int sizemess = 0;
        recv(massaccept[sock], (char*)&sizemess, sizeof(int), NULL);
        mes = new char[sizemess];
        recv(massaccept[sock], mes, sizemess, NULL);

        for (int i = 0; i < size; i++)
        {
            if (i == sock)
            {
                i = i;
            }
            else
            {
                option a = option::takemes;
                send(massaccept[i], (char*)&a, sizeof(option), NULL);
                send(massaccept[i], (char*)&sizemess, sizeof(int), NULL);
                send(massaccept[i], mes, sizemess, NULL);
            }
        }
        delete[]mes;
        return true;
    }
    case sendservermes:
    {
        char* mes = nullptr;
        int sizemess = 0;
        recv(massaccept[sock], (char*)&sizemess, sizeof(int), NULL);
        mes = new char[sizemess];
        recv(massaccept[sock], mes, sizemess, NULL);
        std::cout << mes;
        return true;

    }
    case closesock:
    {
        std::cout << "Зв'язок розірвано." << std::endl;
        int pos = 0;
        option a = option::takemes;
        send(massaccept[sock],(char*)&a, sizeof(option), NULL);
        send(massaccept[sock], (char*)&pos, sizeof(int), NULL);
        closesocket(massaccept[sock]);
        return false;
    }
    case sendoneposmess:
    {
        char* nm = nullptr;
        int sz = 0;
        recv(massaccept[sock], (char*)&sz, sizeof(int), NULL);
        nm = new char[sz];
        recv(massaccept[sock], nm, sz, NULL);

        int sen = findname(std::string(nm));
        std::cout << sen;
        send(massaccept[sock], (char*)&sen, sizeof(int), NULL);

        if (sen != -1)
        {
            char* mes = nullptr;
            int sizemess = 0;
            recv(massaccept[sock], (char*)&sizemess, sizeof(int), NULL);
            mes = new char[sizemess];
            recv(massaccept[sock], mes, sizemess, NULL);

            option a = takeprivate;
            send(massaccept[sen], (char*)&a, sizeof(option), NULL);
            send(massaccept[sen], (char*)&sizemess, sizeof(int), NULL);
            send(massaccept[sen], (char*)&mes, sizemess, NULL);
        }
        return true;
    }
    default:
    {
        std::cout << "Пакет недоступний." << std::endl;
        return false;
    }
    }
    
}

void work(int pos)
{
    bool wo = true;
    while (wo == true)
    {
        option op = sendallmess ;
        recv(massaccept[pos], (char*)&op, sizeof(option), NULL);
        wo = funcop(op, pos);
    }
}

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

    WSAData data;
    WORD word = MAKEWORD(2, 2);
    person* serv = nullptr;
    if (WSAStartup(word, &data) != 0)
    {
        std::cout << "Не вдалося завантажити бібліотеку." << std::endl;
        return 1;
    }else
    {
        sockaddr_in soin;
        soin.sin_addr.s_addr = inet_addr("127.0.0.1");
        soin.sin_port = htons(666);
        soin.sin_family = AF_INET;
        int size = sizeof(soin);

        SOCKET mainsock = socket(AF_INET, SOCK_STREAM, NULL);
        bind(mainsock, (sockaddr*)&soin, size);
        listen(mainsock, SOMAXCONN);

        for (int i = 0; i < size; i++)
        {
            SOCKET newaccept = accept(mainsock, (sockaddr*)&soin, &size);
            if (newaccept == 0)
            {
                std::cout << "Клієнт не підключений." << std::endl;
                closesocket(newaccept);
            }
            else
            {
                person* find = new person;
                recv(newaccept, (char*)find, sizeof(person), NULL);
                line(&massper, "135", 53113316);
                line(&massper, "1ggeq", 533111316);
                line(&massper, find->name,find->pass);
                bool close = findpass(find);
                if (close == false)
                {
                    std::cout << "Невдала спроба входу." << std::endl;
                    send(newaccept, (char*)&close, sizeof(bool), NULL);
                    closesocket(newaccept);
                }
                else
                {
                    send(newaccept, (char*)&close, sizeof(bool), NULL);
                    std::cout << "Клієнт " << find->name << " підключений." << std::endl;
                    std::string mess = "Вітаємо на сервері ";
                    std::string nim = find->name;
                    std::string en = ".";
                    std::string line = mess + nim + en;
                    line.push_back('\n');
                    line.push_back('\0');
                    int sizemess = line.size();
                    send(newaccept, (char*)&sizemess, sizeof(int), NULL);
                    send(newaccept, line.c_str(), sizemess, NULL);

                    /*char* mes = nullptr;
                    int pos = NULL;
                    recv(newaccept, (char*)&pos, sizeof(int), NULL);
                    mes = new char[pos];
                    recv(newaccept, mes, pos, NULL);
                    std::cout << mes;
                    delete[] mes;*/
                    massaccept[i] = newaccept;
                    massth[i] = std::thread(work, i);
                }
            }
        }
        
    }
    for (int i = 0; i < size; i++)
    {
        massth[i].join();
    }
    WSACleanup();
    return 0;
}

ось код клієнта

#include <iostream>
#include <string>
#include <WinSock2.h>
#include <thread>

#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable : 4996)

SOCKET mainsock;

struct person
{
    std::string name;
    int pass;
    person* next;
};
person* newper = new person;


enum option
{
    sendallmess,
    sendoneposmess,
    sendservermes,
    takemes,
    closesock,
    takeprivate
};

bool funcop(option op)
{
    switch (op)
    {
    case sendallmess:
    {
        std::string premes = "Вам надійшло повідомлення: ";
        std::string mes;
        std::cin >> mes;
        std::string line = premes + mes;

        line.push_back('\n');
        line.push_back('\0');

        int size = line.size();
        option sendall = sendallmess;
        send(mainsock, (char*)&sendall, sizeof(option), NULL);
        send(mainsock, (char*)&size, sizeof(int), NULL);
        send(mainsock, line.c_str(), size, NULL);

        return true;
    }
    case takemes:
    {
        char* mes = nullptr;
        int sizemess = NULL;
        recv(mainsock, (char*)&sizemess, sizeof(int), NULL);
        if (sizemess == 0)
        {
            return false;
        }
        else
        {
            mes = new char[sizemess];
            recv(mainsock, mes, sizemess, NULL);
            std::cout << mes;
            delete[] mes;
            return true;
        }
    }
    case sendservermes:
    {

        std::string premes = "Вам надійшло повідомлення від ";
        std::string mes;
        std::string nm = newper->name;
        std::string last = ": ";
        std::cin >> mes;
        std::string line = premes + nm + last + mes;

        line.push_back('\n');
        line.push_back('\0');


        int size = line.size();
        option sendall = sendservermes;
        send(mainsock, (char*)&sendall, sizeof(option), NULL);
        send(mainsock, (char*)&size, sizeof(int), NULL);
        send(mainsock, line.c_str(), size, NULL);

        return true;
    }
    case closesock:
    {
        option op = option::closesock;
        send(mainsock, (char*)&op, sizeof(option), NULL);
        std::cout << "Зв'язок розірвано." << std::endl;
        return false;
    }
    case sendoneposmess:
    {
        std::cout << "Введіть ім'я користувача: ";
        std::string nam;
        std::cin >> nam;
        int ln = 0;
        option c = sendoneposmess;
        nam.push_back('\0');
        ln = nam.size();

        send(mainsock, (char*)&c, sizeof(option), NULL);
        send(mainsock, (char*)&ln, sizeof(int), NULL);
        send(mainsock, nam.c_str(), ln, NULL);
        int sen = -1;

        recv(mainsock, (char*)&sen, sizeof(int), NULL);

        if (sen != -1)
        {
            std::cout << "Введіть повідомлення користувачу " << nam << ": ";
            std::string premes = "Вам надійшло повідомлення від ";
            std::string pi = newper->name;
            std::string last = ": ";
            std::string mes;
            std::cin >> mes;
            std::string line = premes + pi + last + mes;

            line.push_back('\n');
            line.push_back('\0');

            int size = line.size();
            send(mainsock, (char*)&size, sizeof(int), NULL);
            send(mainsock, line.c_str(), size, NULL);

        }
        return true;

    }
    case takeprivate:
    {
        char* mes = nullptr;
        int sizemess = 0;
        recv(mainsock, (char*)&sizemess, sizeof(int), NULL);
        mes = new char[sizemess];
        recv(mainsock, mes, sizemess, NULL);
        std::cout << mes;
        return true;
    }
    default:
        std::cout << "Пакет недоступний." << std::endl;
        return false;
    }
    return true;
}

void take()
{
    bool po = true;
    while (po == true)
    {
        option a = takemes;
        recv(mainsock, (char*)&a, sizeof(option), NULL);
        po = funcop(a);
    }
    return;
}

void work()
{
    bool bo = true;
    while (bo == true)
    {
        std::cout << "Введіть операцію (0 - sendallmess, 1 - sendoneposmess, 2 - sendservermes, 3 - closesock): " << std::endl;
        int pos = 0;
        std::cin >> pos;
        switch (pos)
        {
        case 0:
        {
            option op = option::sendallmess;
            bo = funcop(op);
            break;
        }
        case 1:
        {
            option op = option::sendoneposmess;
            bo = funcop(op);
            break;
        }
        case 2:
        {
            option op = option::sendservermes;
            funcop(op);
            break;
        }
        case 3:
        {
            option op = option::closesock;
            bo = funcop(op);
            break;
        }
        default:
            std::cout << "Помилка." << std::endl;
            break;
        }
    }
}

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

    WSAData data;
    WORD word = MAKEWORD(2, 2);
    std::thread mas[2];


    newper->name = "Qlo";
    newper->pass = 123;

    if (WSAStartup(word, &data) != 0)
    {
        std::cout << "Не вдалось завантажити бібліотеку." << std::endl;
        return 1;
    }
    else
    {
        sockaddr_in soin;
        soin.sin_addr.s_addr = inet_addr("127.0.0.1");
        soin.sin_port = htons(666);
        soin.sin_family = AF_INET;
        int size = sizeof(soin);

        mainsock = socket(AF_INET, SOCK_STREAM, NULL);
        SOCKET connserv = connect(mainsock, (sockaddr*)&soin, size);

        if (connserv != 0)
        {
            std::cout << "Не вдалося підключитись до серверу." << std::endl;
            return 2;
        }
        else
        {
            std::cout << "Підключено до серверу." << std::endl;
            bool lock = false;
            send(mainsock, (char*)newper, sizeof(person), NULL);

            recv(mainsock, (char*)&lock, sizeof(bool), NULL);
            if (lock == false)
            {
                std::cout << "Помилка входу." << std::endl;
                return 10;
            }
            else
            {
                int sizemes = NULL;
                char* mes = nullptr;

                recv(mainsock, (char*)&sizemes, sizeof(int), NULL);
                mes = new char[sizemes];
                recv(mainsock, mes, sizemes, NULL);
                std::cout << mes;


                mas[0] = std::thread(work);
                mas[1] = std::thread(take);
            }
        }
    }
    for (int i = 0; i < 2; i++)
    {
        mas[i].join();
    }
    WSACleanup();
    return 0;
}

Re: Потоки

Хочу щоб повідомлення відправлялось конкретному користувачеві, а не всім разом, як реалізовано у першій функ

31

Re: Потоки

Так а що, зараз не відправляється?

Re: Потоки

Що?

Re: Потоки

Я, мабуть , зрозумів проблему. Там функція, яка отримує повідомлення краде дані постійно, і вони не оброблюються в основній функції (для віфдправки певній особі) . Але без поняття як це виправити

Re: Потоки

Все, працює.

Re: Потоки

В мене походу шиза, сам з собою спілкуюсь. Видальте останні декілька моїх повідомлень, будь ласка)

Подякували: 0xDADA11C71

36

Re: Потоки

Львовский сырник в мульти написав:

В мене походу шиза, сам з собою спілкуюсь. Видальте останні декілька моїх повідомлень, будь ласка)

Прихований текст

те, що у вас шиза, було зрозуміло відразу після вашої реєстрації на форумі

Подякували: Betterthanyou, /KIT\, 0xDADA11C7, leofun014