Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
 Отправить задание c++ серверу  [new]
ro25man
Member

Откуда:
Сообщений: 3
Здравствуйте
Решил поизучать серверные приложений на c++ и написать простенький сервер, выполняющий запросы клиента. Есть клиент, с которого я отправляю запрос, чтобы выполнить какую-либо операцию на сервере. Пусть это будет функция, возвращающая текущее время getTime(). Как заставить сервер выполнить эту функцию?
Единственное предположение - это передавать какой-то признак (текст, число), который будет привязан к функции getTime(). На сервере добавить переменную и выполнять её обработку через if или switch. Это выглядит примерно так:
if (param == "getTime")
getTime();
и т.д. для каждой функции сервера. То есть если на сервере будет 1000 таких функций, то для каждой из них мне нужно будет делать ветку else if? Аналогично при использовании оператора switch.
Есть другие способы для выполнения таких запросов или это единственный?
28 дек 20, 22:00    [22256037]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

ro25man
Есть другие способы для выполнения таких запросов или это единственный?

Единственный.

Posted via ActualForum NNTP Server 1.5

28 дек 20, 23:16    [22256065]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
mayton
Member

Откуда: loopback
Сообщений: 51019
В вопросе есть два вопроса.

Первое - это протокол. Как передать по сети. Да хоть так.

wget http://ro25man.com/server?argument=getTime


Второе - это реализация. Можно switch. Можно if. Можно еще много чего придумать
но ты начни хотя-бы с клиент-сервера на сокетах.
28 дек 20, 23:54    [22256083]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
ъъъъъ
Member

Откуда:
Сообщений: 1966
ro25man
Есть другие способы для выполнения таких запросов или это единственный?

От используемых технологий зависит.
Например, реализуя сервер как Web сервис/службу, ты напрямую создаешь на сервере реализацию нужных методов. А клиент обращается прямо к нужному методу. Далее волшебным образом запрос клиента преобразуется в запрос низкого уровня, поток данных передается на сервер, где-то невидимо от тебя выполняется цепочка else-if, и вызывается нужны тебе метод, результат возвращается клиенту. Подобных технологий и библиотек - масса.
30 дек 20, 00:59    [22256863]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
tip78
Member

Откуда: Москва
Сообщений: 1266
гугли "c++ client-server"
mayton
Да хоть так.

wget http://ro25man.com/server?argument=getTime

это целый HTTP-сервер нужен )
а у него просто сокеты

Сообщение было отредактировано: 30 дек 20, 09:45
30 дек 20, 09:50    [22256901]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34688
ro25man

Единственное предположение - это передавать какой-то признак (текст, число), который будет привязан к функции getTime(). На сервере добавить переменную и выполнять её обработку через if или switch. Это выглядит примерно так:
if (param == "getTime")
getTime();
и т.д. для каждой функции сервера. То есть если на сервере будет 1000 таких функций, то для каждой из них мне нужно будет делать ветку else if? Аналогично при использовании оператора switch.
Есть другие способы для выполнения таких запросов или это единственный?


Эта штука называется "сетевой протокол" и тебе надо либо придумать свой, либо использовать существующие.

При этом конечно IF/SWITCH там в коде в явном виде может и не быть, но суть действий всё равно такая: по какому-то типу запроса будут вызываться на выполнение какие-то действия. И от этого IF/SWITCH конечно же никуда не уйти.
30 дек 20, 09:58    [22256908]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
mayton
Member

Откуда: loopback
Сообщений: 51019
tip78
гугли "c++ client-server"
mayton
Да хоть так.

wget http://ro25man.com/server?argument=getTime

это целый HTTP-сервер нужен )
а у него просто сокеты

А расскажи какая разница между HTTP сервером и сокетами? Или протоколом telnet. Тоесть насколько она велика.

И как вообще можно построить протокол на сокетах?
30 дек 20, 10:55    [22256943]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 7650
MasterZiv,
+1
Слово просто "сервер" не существует. Без указания протокола/архитектуры.
Есть сокет сервер, веб сервер, аппСервер, фтпСервер.....
30 дек 20, 11:16    [22256962]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

mayton
А расскажи какая разница между HTTP сервером и сокетами? Или протоколом telnet. Тоесть
насколько она велика.

Размером в сумму всех RFC, расписывающих HTTP заголовки и соответствющие им форматы
данных. Несколько мегабайт нужного чтения наберётся.

Posted via ActualForum NNTP Server 1.5

30 дек 20, 13:12    [22257110]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
mayton
Member

Откуда: loopback
Сообщений: 51019
Dimitry Sibiryakov

mayton
А расскажи какая разница между HTTP сервером и сокетами? Или протоколом telnet. Тоесть
насколько она велика.

Размером в сумму всех RFC, расписывающих HTTP заголовки и соответствющие им форматы
данных. Несколько мегабайт нужного чтения наберётся.

Автор - пытается построить свой протокол. Я предполагаю что поверх сокетов. Хотел предложить ему
сначала telnet как клиента. И спецификацию команд наподобие упрощенного http. Типа POST/GET.
30 дек 20, 13:35    [22257138]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

mayton
И спецификацию команд наподобие упрощенного http. Типа POST/GET.

Ты же знаешь, что парсинг тестового потока в С/С++ - занятие не для слабонервных...

Posted via ActualForum NNTP Server 1.5

30 дек 20, 13:43    [22257150]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
mayton
Member

Откуда: loopback
Сообщений: 51019
Мда... согласен.
30 дек 20, 13:48    [22257155]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
Basil A. Sidorov
Member

Откуда:
Сообщений: 10925
Я бы сказал, что разбор любого потока требует аккуратности, сосредоточенности и изобретательности.
Вне зависимости от языка
30 дек 20, 14:06    [22257171]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
tip78
Member

Откуда: Москва
Сообщений: 1266
mayton
tip78
гугли "c++ client-server"
пропущено...

это целый HTTP-сервер нужен )
а у него просто сокеты

А расскажи какая разница между HTTP сервером и сокетами? Или протоколом telnet. Тоесть насколько она велика.

И как вообще можно построить протокол на сокетах?

парсинг форм в fCGI - это отдельная, долгая, грустная, вопиющая песня.
обработка заголовков и роутинг - ещё пара очень грустных песен.
Простенький сервер на сокетах же просто принимает сигнал, не сильно сложнее ping-pong, и реагирует на него списком if-ов.

Задачу с протоколом не видел, человек просто хотел:
ro25man
написать простенький сервер, выполняющий запросы клиента.
30 дек 20, 17:52    [22257336]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
ro25man
Member

Откуда:
Сообщений: 3
В ответах речь пошла и про http сервер, и про новый протокол. Поясню, как именно я предполагал реализовать сервер.
Использую для работы с сетью WinAPI. Может быть не самое лучшее средство, но для начала, на мой взгляд, вполне подходит. С помощью send() я отправляю запрос от клиента. Так как мне нужно вызвать функцию getTime(), то в буфер записал строку "getTime". На стороне сервера принимаю с помощью recv() данные, читаю буфер. Затем пробегаю по условиям и ищу нужную мне ветку
if (param == "getTime")
getTime();

Далее возвращаю результат клиенту. Собственно мой вопрос и заключался, единственное ли это решение для извлечения данных от сервера или есть другие варианты

Сообщение было отредактировано: 30 дек 20, 21:16
30 дек 20, 21:21    [22257422]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 7650
ro25man,
Вы новый протокол пишите или http server?
Если только протокол то дайте код сервера.
31 дек 20, 11:36    [22257540]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
ro25man
Member

Откуда:
Сообщений: 3
PetroNotC Sharp,

код сервера простой. Взял на просторах интернета как есть, ничего пока не менял. В код добавил комментарий, который начинается фразой "здесь добавить мой код". Вот там и будет выполнена реализация того, что я хочу получить от сервера, мои овердофига функций, классов и т.д.
int main()
{
    WSADATA wsaData;
    int iResult;

    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET ClientSocket = INVALID_SOCKET;

    struct addrinfo* result = NULL;
    struct addrinfo hints;

    int iSendResult;
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) 
    {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the server address and port
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Create a SOCKET for connecting to server
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) 
    {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    // Setup the TCP listening socket
    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR)
    {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    freeaddrinfo(result);

    iResult = listen(ListenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR) 
    {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET)
    {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // No longer need server socket
    closesocket(ListenSocket);

    // Receive until the peer shuts down the connection
    do {

        iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0)        
        {
            printf("Bytes received: %d\n", iResult);

            /* здесь добавить мой код
            if (recvbuf== "anyText")
                anyFunc();
            else if ... и т.д.
            */

            // Echo the buffer back to the sender
            iSendResult = send(ClientSocket, recvbuf, iResult, 0);
            if (iSendResult == SOCKET_ERROR)
            {
                printf("send failed with error: %d\n", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
            printf("Bytes sent: %d\n", iSendResult);
        }
        else if (iResult == 0)
        {
            printf("Connection closing...\n");
        }
        else 
        {
            printf("recv failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }

    } while (iResult > 0);

    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) 
    {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

    // cleanup
    closesocket(ClientSocket);
    WSACleanup();

    return 0;
}
31 дек 20, 13:23    [22257577]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

ro25man
В код добавил комментарий, который начинается фразой *"здесь добавить мой код"*. Вот там и
будет выполнена реализация того, что я хочу получить от сервера, мои овердофига функций,
классов и т.д.

И вот там уже твоя первая ошибка. TCP это поток, recv() способен рубить его на
произвольные части. За раз ты можешь получить только часть того буфера, что отправлял,
или, наоборот, две отправки будут слеплены вместе. Поэтому-то выше и говорилось, что
парсинг потока - занятие нетривиальное.

Posted via ActualForum NNTP Server 1.5

31 дек 20, 13:35    [22257586]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
mayton
Member

Откуда: loopback
Сообщений: 51019
Тут по идее мультипоточка нужна.
31 дек 20, 14:02    [22257605]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 7650
ro25man,

Я бы делал отдельный бинарник http server и отдельный твой код.
31 дек 20, 15:47    [22257654]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
ptr128
Member

Откуда: Moscow
Сообщений: 887
Dimitry Sibiryakov

Единственный.

А табличный метод отменили уже что-ли?

Делаем табличку в памяти (массив структур) состоящую из отсортированных идентификаторов запроса и указателя на функцию, этот запрос обрабатывающую. Тупым бинарным поиском ищем принятый идентификатор в таблице. Если не найден - ошибка. Если найден - вызываем функцию, обрабатывающий запрос с таким идентификатором передавая ей все остальные параметры запроса.
1 янв 21, 23:41    [22257980]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
tip78
Member

Откуда: Москва
Сообщений: 1266
и чем это лучше if/switch ?
2 янв 21, 00:59    [22257986]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

Я бы даже спросил "чем это отличается от if"...

Posted via ActualForum NNTP Server 1.5

2 янв 21, 01:17    [22257989]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
ъъъъъ
Member

Откуда:
Сообщений: 1966
ptr128
Dimitry Sibiryakov

Единственный.

А табличный метод отменили уже что-ли?

Делаем табличку в памяти (массив структур) состоящую из отсортированных идентификаторов запроса и указателя на функцию, этот запрос обрабатывающую. Тупым бинарным поиском ищем принятый идентификатор в таблице. Если не найден - ошибка. Если найден - вызываем функцию, обрабатывающий запрос с таким идентификатором передавая ей все остальные параметры запроса.

Делаем табличку в памяти, состояющую из указателей на реализации методов.
В запросе передаем индекс метода, вместо его имени.
Сервер обращается к методу по индексу. Далее метод выполняет специфичный для него код (например, выбирает из тела запроса значения входных параметров метода и т.п.).
2 янв 21, 01:53    [22257991]     Ответить | Цитировать Сообщить модератору
 Re: Отправить задание c++ серверу  [new]
ъъъъъ
Member

Откуда:
Сообщений: 1966
То есть, сервер обращается к реализации метода за один шаг, как к элементу массива.

Сообщение было отредактировано: 2 янв 21, 02:01
2 янв 21, 02:06    [22257992]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
Все форумы / C++ Ответить