Нет ответа от Aerospike
Пишу свой клиент для Aerospike на C++. Написал простой TCP-клиент, который работает с обычными серверами (1.1.1.1 возвращает Bad request, что ожидаемо). Однако с Aerospike что-то пошло не так: хоть он и принимает мой запрос (это можно проверить, изменив отправляемое сообщение на бессмыслицу типа "hello" - соединение тут же сбросится), но и ответа не отправляет.
Код:
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <iostream>
void read_message(boost::asio::ip::tcp::socket& socket)
{
for (;;)
{
boost::array<char, 1> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
break;
else if (error)
throw boost::system::system_error(error);
std::cout.write(buf.data(), len);
std::cout << std::endl;
}
}
void send_message(boost::asio::ip::tcp::socket& socket, std::string message)
{
boost::array<char, 1024> buf;
std::copy(message.begin(), message.end(), buf.begin());
boost::system::error_code error;
socket.write_some(boost::asio::buffer(buf, message.size()), error);
}
int main()
{
std::cout << "Connecting to socket.." << std::endl;
boost::asio::io_service ios;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 3000);
boost::asio::ip::tcp::socket socket(ios);
socket.connect(endpoint);
std::cout << "Connected to socket. Writing message." << std::endl;
send_message(socket, "\x02\x01\x00\x00\x00\x00\x006build\nedition\nnode\nservice\nservices\nstatistics\nversion\n\n");
std::cout << "Wrote message. Reading response." << std::endl;
read_message(socket);
std::cout << "Read response. Exiting prigram." << std::endl;
socket.close();
return 0;
}
Что тут не так? Почему я не могу отловить ответ сервера?
P.S. Aerospike абсолютно точно работает, Python-клиент получает от него корректный ответ.
Ответы (1 шт):
Боюсь что вы напоролись на очень глупую ошибку:
void send_message(boost::asio::ip::tcp::socket& socket, std::string message)
...
send_message(socket, "\x02\x01\x00\x00\x00\x00\x006build\nedition\nnode\nservice\nservices\nstatistics\nversion\n\n");
Как видим: ваша функция принимает строку - все ок (за исключением того, что вы ее содержимое копируете в промежуточный буфер и только потом в сокет). Но что вы передаете в send_message? Вы передаете не std::string, а cstring. Может показаться что это не важно, но не тут то было! cstring должен заканчиваться нулевым байтом... который у вас идет третьим по счету. Лучше всего ситуацию продемонстрирует следующий пример:
const char c_str[] = "\x02\x01\x00\x00\x00\x00\x006build\nedition\nnode\nservic"
"e\nservices\nstatistics\nversion\n\n";
std::string str = c_str;
std::cout << sizeof(c_str) << std::endl; // -> 63
std::cout << str.size() << std::endl; // -> 2
Почему так? Потому что в данном случае был вызван конструктор, который создает строку из const char *, а для него не известен размер, поэтому строка считывается пока не встретится нулевой байт (cstring). Но, вы можете сами задать сколько байт считать в строку:
std::string str{c_str, sizeof(c_str)};
В этом случае в строку будет считано все содержимое литерала. Однако помните: sizeof выдаст размер строки только для литерала - если же это const char *, то оно выдаст размер указателя.
Вообще вы могли бы сразу выявить проблему проверив что вы пытаетесь отправить - странно что вы этого не сделали.