Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

PaiMeiPetrovich
Писатель
Сообщения: 36
Зарегистрирован: 26 авг 2022, 20:56
Контактная информация:

Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение PaiMeiPetrovich » 18 сен 2022, 18:31

Мое почтение! Надобно реализовать 2 программы, собственно говоря, насколько я понимаю, одна программа это "клиент", который ждет ввода с консоли, затем обрабатывает данные и посылает их 2-й программе, которая эти данные обрабатывает и в консольку что-то тоже выводит (сервер).
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Клиент: состоит из 2-х потоков и общего буфера. Первый поток принимает строку на вход и кладет ее в тот самый буфер, затем ждет следующий ввод данных. Второй поток берет строку из буфера, зачищает этот буфер и передает эту строку серверу, а далее ждет новых данных из буфера. Взаимодействие потоков должно быть синхронизировано без помощи глобальной переменной.

Сервер: ждет данные от клиента, получив их как-то их обрабатывает (допустим, к полученной строке добавляет "Hello from server!") и продолжает ждать следующих данных.

Взаимодействие клиента и сервера надобно реализовать с помощью сокетов.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Далее, прикладываю примерный скелет программы:
socket_serv.cpp
Скелет сервера
(2.16 КБ) 32 скачивания
socket_client.cpp
Скелет Клиента, на одну итерацию
(1.43 КБ) 35 скачиваний
threads.cpp
Примерное взаимодействие потоков внутри клиента
(1.49 КБ) 36 скачиваний
Знаю, что мой код явно не лучший вариант, хотелось бы увидеть человеческий вариант кода в целом по программе.
И синхронизацию между потоками, может быть, как-то по-другому реализовать, не как у меня ( а то у меня там вроде как глобальная переменная, хотя я пометил ее "static", что должно означать, что она глобальна только в рамках этого файла (насколько я понимаю), да и без задержек времени может быть, как-то...)

PaiMeiPetrovich
Писатель
Сообщения: 36
Зарегистрирован: 26 авг 2022, 20:56
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение PaiMeiPetrovich » 18 сен 2022, 18:39

Ааа, ну, может быть, с помощью "pthread_join " сишного синхронизировать (ну на плюсах что-то подобное наверняка есть).

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 00:57

PaiMeiPetrovich писал(а):
18 сен 2022, 18:31
Взаимодействие клиента и сервера надобно реализовать с помощью сокетов.
Я когда то, давно, плотно работая с сетями по служеьным обязанностям, написал пару статей, которые могут вам быть очень интересными в связи с вашейй задачей. Это написано было в 2003 году ... потом до 2012 года переписывалось (улучшалось?).
Вот упоминание этих 2-х статей: суперсервера inetd/xinetd в своих целях ... но все ссылки с тех времён посыпались...
Olej писал(а):
23 апр 2012, 20:45
А вот ещё 2 статьи:
- Сеть IP - когда писать программы лень
- Сервер TCP/IP... много серверов хороших и разных
Но оно столько раз множилось по Интернет, что я сейчас найду актуальные ссылки... Даже если они вам не пригодятся, то мне самому полезными будут, потому что я потерял эти свои публикации...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 01:00

Olej писал(а):
19 сен 2022, 00:57
я сейчас найду актуальные ссылки...
Olej писал(а):
19 сен 2022, 00:57
Сервер TCP/IP... много серверов хороших и разных
Сервер TCP/IP ... много серверов хороших и разных
И сам архив кодов к тексту:
Вложения
xservers.5.tgz
(140.84 КБ) 30 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 01:23

Olej писал(а):
19 сен 2022, 00:57
Сеть IP - когда писать программы лень
Сеть IP — когда писать программы лень
Эта заметка, может, и менее полезна конкретно, но она даёт инструмент для очень простой и эффективной отладки сетевых приложений.
Вложения
xinetd.1.tgz
(135.04 КБ) 34 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 01:26

PaiMeiPetrovich писал(а):
18 сен 2022, 18:39
может быть, с помощью "pthread_join " сишного синхронизировать (ну на плюсах что-то подобное наверняка есть)
А по поводу синхронизаций - посмотрите обстоятельно здесь: Параллелизм, конкурентность, многопроцессорность в Linux

P.S. И даже, чтобы далеко не лазить, я вам сюда прикреплю и текст и коды...
Вложения
SMP_05.odt
(180.81 КБ) 32 скачивания
examples.SMP.05.tgz
(307.37 КБ) 32 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 10:26

PaiMeiPetrovich писал(а):
18 сен 2022, 18:39
может быть, с помощью "pthread_join " сишного синхронизировать (ну на плюсах что-то подобное наверняка есть).
В Linux/UNIX (тут большое отличие от Windows) всё взаимодействие любой C++ программы с системой (системными вызовами) идёт всё-равно черезстандартную библиотеку языка C - libc.so. Поэтому любые вызовы API POSIX/Linux языка C можно использовать в неизменном виде с коде C++.

P.S. Хотя адепты секты "чистого C++" на этом месте соплями изойдут: "как же так можно!" :lol:

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 10:29

PaiMeiPetrovich писал(а):
18 сен 2022, 18:31
Надобно реализовать 2 программы
Это что? для чего?
1). учебное задание ... в каком-то учебном заведении
2). для себя какая-то поделка, чтобы мспользовать самому в каких-то целях
3). составная часть какого-то разработческого проекта ... работа в силу служеьной обязанности

В зависимости от того что это - его по разному можно (нужно :-D ) писать.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 10:47

PaiMeiPetrovich писал(а):
18 сен 2022, 18:39
(ну на плюсах что-то подобное наверняка есть).
По C++ держите открытыми под рукой вот эти онлайновые справочники - чтоб сразу легко находить то что надо ... например по mutex:
https://en.cppreference.com/w/cpp/thread/mutex
https://cplusplus.com/reference/mutex/mutex/
(мне 2-й больше нравится, но это дело вкуса)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Простейшая реализация клиент-серверного консольного приложения через сокеты на с++

Непрочитанное сообщение Olej » 19 сен 2022, 11:48

PaiMeiPetrovich писал(а):
18 сен 2022, 18:31
И синхронизацию между потоками, может быть, как-то по-другому реализовать, не как у меня ( а то у меня там вроде как глобальная переменная, хотя я пометил ее "static", что должно означать, что она глобальна только в рамках этого файла (насколько я понимаю), да и без задержек времени может быть, как-то...)
Никогда! Никогда нельзя использовать временные задержки (паузы) для предписывания порядка действий параллельных ветвей! И особенно пассивных временных задержек (типа sleep(), delay() ...).
Последовательность действий параллельных ветвей должна определяться только синхронипзациями (использованием механизмов синхронизации)!

Я переписал (по-быстрому, на вскидку) ваш пример threads.cpp с использованием условной переменной:

Код: Выделить всё

#include <thread>
#include <iostream>
#include <mutex>
#include <cstring>
#include <condition_variable>

#define BUFF_SIZE 10
char buf[BUFF_SIZE + 1];  // через этот буфер идет обмен данными

std::mutex mx;            // мутекс, обеспечивающий синхронизацию потоков
std::condition_variable_any cv;
bool ready = false;

void    dosth() {
    while(true) {
        // задержка, обеспечивающая синхронизацию мутексов
        // std::this_thread::sleep_for(std::chrono::milliseconds(200));
        mx.lock();
        cv.wait(mx, []{return ready;});        
        std::cout << "Hello FROM DOSTH: " << buf << std::endl;
        ready = false;        
        mx.unlock();
    }
}

int main() {
    std::thread t(dosth); // создаем 2-й поток
    // t.detach();
    std::string msg;      // сюда данные с консоли запишем
    while (true) {
        std::cout<<"Please enter the line!"<<std::endl;
        getline(std::cin, msg);
        /* while (msg.size() > BUFF_SIZE) {
            printf("too much string, go again!\n");
            getline(std::cin, msg);
        }*/
        mx.lock();        
        strncpy(buf, msg.c_str(), BUFF_SIZE);
        ready = true;
        cv.notify_one();        
        mx.unlock();
        // задержка, обеспечивающая синхронизацию мутексов
        // std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    return 0;
}

Код: Выделить всё

olej@R420:~/2022/own.BOOKs/TCPIP-сервер/С++$ c++ threads.cpp -l pthread -o threads
И вот что из этого получилось:

Код: Выделить всё

olej@R420:~/2022/own.BOOKs/TCPIP-сервер/С++$ ./threads 
Please enter the line!
123
Please enter the line!
Hello FROM DOSTH: 123
123456789012345
Please enter the line!
Hello FROM DOSTH: 1234567890
4321
Please enter the line!
Hello FROM DOSTH: 4321
^C
Я специально не стал добавлять синхронизацию вывода приглашения "Please enter the line!" ... (Потому что у вас достаточно искусственные условия задачи, когда 2 части должны выполняться как-раз последовательно, тут не нужны потоки и параллельность).
Вложения
threads.cpp
(1.53 КБ) 31 скачивание

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 15 гостей