LINUX.ORG.RU

постоянная синхронная отправка запросов и получения ответов

 , ,


0

1

Взял пример отсюда: И отсюда:

Скрестил ужа с ежом:

int main(int argc, char* argv[])
{

    boost::asio::io_service io_service;
    boost::asio::ip::tcp::endpoint endpoint (boost::asio::ip::address::from_string("192.168.0.1"), 1234);
    boost::asio::ip::tcp::socket sock(io_service);
    sock.open(boost::asio::ip::tcp::v4());
    sock.connect(endpoint);

    for (int i=0;i<2;i++){
            std::cout << "Enter message: ";
            char request[max_length];
            std::cin.getline(request, max_length);

            size_t request_length = strlen(request);
            sock.write_some(boost::asio::buffer(request, request_length));

            char reply[max_length];

            size_t reply_length = sock.read_some(boost::asio::buffer(reply, 1024));

            std::cout << "Reply is: ";
            std::cout.write(reply, reply_length);
            std::cout << "\n";
    }
  return 0;
}

первый раз срабатывает на отличненько, а на второй не получаю ответа.

Задача: постоянно опрашивать синхронно объект.

★★★★★

Последнее исправление: sniper21 (всего исправлений: 1)

С read_some() осторожнее:

The read_some operation may not read all of the requested number of bytes. Consider using the read function if you need to ensure that the requested amount of data is read before the blocking operation completes.

С write_some() та же фигня. А что на второй раз происходит? Блокируется навечно или считывает мусор?

Deleted
()

Какое-то у вас упорство в использовании Boost.Asio для работы по HTTP. Почему бы не взять libcurl?

Ну или Boost.Beast из Boost-1.66, если так уж хочется именно Boost-а.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Ну или Boost.Beast из Boost-1.66

Мне легко пока доступен только 1.48.

Какое-то у вас упорство в использовании Boost.Asio для работы по HTTP.

Может я чего не понимаю, но я через TCP сокеты работаю, на три уровеня(?) ниже HTTP.

Почему бы не взять libcurl?

Брал, сейчас работает в продакшене (синхронно).

sniper21 ★★★★★
() автор топика
Последнее исправление: sniper21 (всего исправлений: 1)
Ответ на: комментарий от sniper21

Может я чего не понимаю, но я через TCP сокеты работаю, на три уровеня(?) ниже HTTP.

Если вы по TCP гоняете данные в соответствии с HTTP-протоколом, то вы обманываете сами себя.

eao197 ★★★★★
()
Ответ на: комментарий от Deleted

поправил на send/receive. Работает также - ничего не поменялось. Добавил проверки, может чего «выбросит» - пусто.

int main(int argc, char* argv[])
{

    boost::asio::io_service io_service;
    boost::asio::ip::tcp::endpoint endpoint (boost::asio::ip::address::from_string("127.0.0.1"), 80);
    boost::asio::ip::tcp::socket sock(io_service);
    boost::system::error_code error_code;
    sock.open(boost::asio::ip::tcp::v4());
    sock.connect(endpoint, error_code);

    if (error_code)
    {
            throw std::runtime_error("Connecting to server FAILED.");
    }

    std::cout << "Connected to " << sock.remote_endpoint().address().to_string() << std::endl;

    for (int i=0;i<2;i++){
            std::cout << "Enter message: ";
            char request[max_length];
            std::cin.getline(request, max_length);

            size_t request_length = strlen(request);
            sock.send(boost::asio::buffer(request, request_length));

            char reply[max_length];

            size_t reply_length = sock.receive(boost::asio::buffer(reply, 1024), 0, error_code);
            if (error_code)
            {
                    throw std::runtime_error("Error while receiving bytes.");
            }

            std::cout << "Reply is: ";
            std::cout.write(reply, reply_length);
            std::cout << "\n";
    }
  return 0;
}

sniper21 ★★★★★
() автор топика
Ответ на: комментарий от eao197

Нет,

Если вы по TCP гоняете данные в соответствии с HTTP-протоколом

sock.write_some(buffer(«GET /index.html\r\n»));

вбил для примера, на самом деле там строка \r\n на конце

sniper21 ★★★★★
() автор топика

Какой-то тупняк...

Тебе в первом сообщении написали уже. У тебя вообще буй поймешь в каком состоянии обмен между клиентом и сервером.

anonymous
()
Ответ на: комментарий от sniper21

С receive()/send() та же фигня:

The receive operation may not receive all of the requested number of bytes. Consider using the read function if you need to ensure that the requested amount of data is read before the blocking operation completes

Используй boost::asio::read(sock,boost::asio::buffer(reply,1024)) для приёма и boost::asio::write(sock,boost::asio::buffer(request,request_length)) для отправки данных. Использовать варианты функций с boost::system::error_code не обязательно - без них он сам исключения кидает. Дальше трассировать нужно: такое чуство, что либо до peer-а не всё доходит, либо он сам по каким-то причинам второй раз не отвечает/завершается после первого круга etc.

P. S. Я надеюсь по адресу 127.0.0.1:80 не кто попало слушает, или это для примера?

Deleted
()
Ответ на: комментарий от Deleted

Используй boost::asio::read(sock,boost::asio::buffer(reply,1024)) для приёма и boost::asio::write(sock,boost::asio::buffer(request,request_length)) для отправки данных.

А этим даже первого ответа нет.

Я надеюсь по адресу 127.0.0.1:80 не кто попало слушает, или это для примера?

Для примера. Там есть браузерный интерфейс и он работает, т.е проблема не с сетью. :(

sniper21 ★★★★★
() автор топика
Ответ на: комментарий от sniper21

В протоколе верхнего уровня ошибка(imho впрочем). У тебя запрос читается посредством std::basic_istream<>::getline(). Если вышележащий протокол является line-based - возможно это и есть ошибка, поскольку getline терминатор не присоединяет(по умолчанию как раз '\n'). Ну и вот это: '\n' vs '\r\n' - хз как peer обрабатывает(может один из вариантов не понимать). Если в запросе есть символы помимо ASCII, следует проверить в какой кодировке они с клиента уходят и в какой их ждёт сервер. Если есть возможность - вруби подробные логи на обеих сторонах и попробуй раскурить их

Deleted
()
Ответ на: комментарий от sniper21

Тогда тебе нужно считывать минимальную длину за раз(1 символ в пределе), анализировать его и если считана только часть ответа - считать следующую порцию. Что значит анализировать: tcp занимается передачей потока данных и никакого деления на части не выполняет(tcp пакеты на прикладном уровне не видны, ибо не нужно) - границы разных сообщений(например, предыдущего и следующего) определяются протоколом верхнего уровня. Зачастую, в таких протоколах в одном из первых полей передаётся длина всего сообщения - проанализировав это поле, можно понять, сколько ещё дочитать.

Можно использовать, например, вот это: http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/reference/transfer_at_least.html(там и пример есть)

Deleted
()
Ответ на: комментарий от Deleted

Вот как надо было отправлять данные:

char request[max_length] = {'g','e','t','i','n','f','o','\r','\n','\0'};

вопрос: почему не срабатывало:

std::cin.getline(request, max_length);
size_t request_length = strlen(request);

?

sniper21 ★★★★★
() автор топика
Последнее исправление: sniper21 (всего исправлений: 1)
Ответ на: комментарий от sniper21

getline()(from http://en.cppreference.com/w/cpp/io/basic_istream/getline):

The delimiter is extracted [...] and counted towards gcount(), but is not stored

Символа конца строки('\r\n' в твоём случае) в запросе не было. Я здесь подробнее писал. Можешь под отладчиком посмотреть результат выполнения getline

Deleted
()
21 июля 2019 г.
Ответ на: комментарий от sniper21

Здравствуйте,

А второй раз Вы отсылали сообщение по тому же самому адрессу ?

Optimus1
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.