auto-reconnect and don't drop messages

This commit is contained in:
Thomas Lindner 2022-05-20 18:55:22 +02:00
parent 586889f543
commit 173182f8e7

View file

@ -6,11 +6,13 @@
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp> #include <boost/asio/read_until.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/streambuf.hpp> #include <boost/asio/streambuf.hpp>
#include <boost/asio/use_awaitable.hpp> #include <boost/asio/use_awaitable.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#include <iostream> #include <iostream>
#include <random> #include <random>
#include <sstream>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
@ -40,6 +42,7 @@ std::string_view DirectionToString(Direction direction) {
class Bot { class Bot {
asio::any_io_executor executor; asio::any_io_executor executor;
asio::steady_timer timer;
asio::ip::tcp::socket socket; asio::ip::tcp::socket socket;
std::string name; std::string name;
std::string pass; std::string pass;
@ -62,6 +65,7 @@ class Bot {
Bot::Bot(asio::any_io_executor executor, std::string_view name, Bot::Bot(asio::any_io_executor executor, std::string_view name,
std::string_view pass) std::string_view pass)
: executor{executor}, : executor{executor},
timer{executor},
socket{executor}, socket{executor},
name{name}, name{name},
pass{pass}, pass{pass},
@ -72,51 +76,68 @@ Bot::Bot(asio::any_io_executor executor, std::string_view name,
asio::awaitable<void> Bot::Protocol() { asio::awaitable<void> Bot::Protocol() {
asio::ip::tcp::resolver resolver{executor}; asio::ip::tcp::resolver resolver{executor};
asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"}; asio::ip::tcp::resolver::query query{"94.45.241.27", "4000"};
auto host = co_await resolver.async_resolve(query, asio::use_awaitable);
co_await asio::async_connect(
socket, co_await resolver.async_resolve(query, asio::use_awaitable),
asio::use_awaitable);
while (true) {
while (true) {
try {
co_await asio::async_connect(socket, host, asio::use_awaitable);
break;
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
timer.expires_after(std::chrono::seconds(1));
co_await timer.async_wait(asio::use_awaitable);
}
try {
while (true) { while (true) {
asio::streambuf buf; asio::streambuf buf;
buf.commit(co_await asio::async_read_until(socket, buf, '\n', co_await asio::async_read_until(socket, buf, '\n', asio::use_awaitable);
asio::use_awaitable));
std::istream is{&buf}; std::istream is{&buf};
std::string line;
while (std::getline(is, line)) {
std::istringstream iss{line};
std::string field; std::string field;
char dummy; char dummy;
std::getline(is, field, '|'); std::getline(iss, field, '|');
if (field == "motd") { if (field == "motd") {
std::getline(is, field); std::getline(iss, field);
std::cout << "-> MotD: " << field << std::endl; std::cout << "-> MotD: " << field << std::endl;
co_await Join(); co_await Join();
} else if (field == "error") { } else if (field == "error") {
std::getline(is, field); std::getline(iss, field);
std::cout << "-> Error: " << field << std::endl; std::cout << "-> Error: " << field << std::endl;
co_return;
} else if (field == "goal") { } else if (field == "goal") {
is >> goal_x >> dummy >> goal_y; iss >> goal_x >> dummy >> goal_y;
std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")" std::cout << "-> Goal is at (" << goal_x << ", " << goal_y << ")"
<< std::endl; << std::endl;
} else if (field == "pos") { } else if (field == "pos") {
is >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >> down >> iss >> x >> dummy >> y >> dummy >> up >> dummy >> right >> dummy >>
dummy >> left; down >> dummy >> left;
std::cout << "-> Position at (" << x << ", " << y << ")" << std::endl; std::cout << "-> Position at (" << x << ", " << y << ")"
#define X(b) (b ? #b ", " : "")
std::cout << " Walls are " << X(up) << X(right) << X(down) << X(left)
<< std::endl; << std::endl;
#define X(b) (b ? #b ", " : "")
std::cout << " Walls are (" << X(up) << X(right) << X(down)
<< X(left) << ")" << std::endl;
#undef X #undef X
co_await ChooseMove(); co_await ChooseMove();
} else if (field == "win" || field == "lose") { } else if (field == "win" || field == "lose") {
int win, lose; int win, lose;
is >> win >> dummy >> lose; iss >> win >> dummy >> lose;
std::cout << "-> You " << field << '!' << std::endl; std::cout << "-> You " << field << '!' << std::endl;
std::cout << " Score: " << win << '/' << lose << std::endl; std::cout << " Score: " << win << '/' << lose << std::endl;
} else { } else {
std::cout << "unhandled message: " << field << '|'; std::cout << "unhandled message: " << field << '|';
std::getline(is, field); std::getline(iss, field);
std::cout << field << std::endl; std::cout << field << std::endl;
} }
} }
}
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
}
co_return; co_return;
} }