Skip to content

Instantly share code, notes, and snippets.

@nerzhul
Created September 26, 2017 21:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nerzhul/8a02cfd49ee4573f32f77c700cb35a59 to your computer and use it in GitHub Desktop.
Save nerzhul/8a02cfd49ee4573f32f77c700cb35a59 to your computer and use it in GitHub Desktop.
asio tcp server/client
#include <iostream>
#include <asio/io_service.hpp>
#include <asio/ip/tcp.hpp>
#include <thread>
#include <asio.hpp>
using asio::ip::tcp;
#define MAX_DATABUF_SIZE 10240
#define HEADER_LEN 4
class GameSession:
public std::enable_shared_from_this<GameSession>
{
public:
GameSession(tcp::socket socket):
m_socket(std::move(socket))
{}
~GameSession()
{
// Called when tcp socket is closed
}
void start()
{
do_read_header();
}
private:
void do_read_header()
{
auto self(shared_from_this());
m_socket.async_read_some(asio::buffer(m_databuffer, HEADER_LEN),
[this, self](std::error_code ec, std::size_t length) {
if (!ec) {
memcpy(&buf_waited_len, &m_databuffer[0], 4);
if (buf_waited_len == 0) {
m_socket.close();
return;
}
std::cout << "Header length waited: " << buf_waited_len << std::endl;
do_read_body();
}
else {
m_socket.close();
return;
}
do_read_body();
});
}
void do_read_body()
{
auto self(shared_from_this());
m_socket.async_read_some(asio::buffer(m_databuffer, buf_waited_len),
[this, self](std::error_code ec, std::size_t length) {
if (!ec) {
std::cout << "Length: " << length << ", Buffer: "
<< std::endl << "===========" << std::endl
<< &m_databuffer[0] << std::endl << "===========" << std::endl;
}
else {
m_socket.close();
return;
}
do_read_header();
});
}
tcp::socket m_socket;
uint32_t buf_waited_len = 0;
std::array<char, MAX_DATABUF_SIZE> m_databuffer;
};
class GameClient
{
public:
GameClient(asio::io_service &io_service, tcp::resolver::iterator endpoint_iterator):
m_socket(io_service),
m_io_service(io_service)
{
do_connect(endpoint_iterator);
}
private:
void do_connect(tcp::resolver::iterator endpoint_iterator)
{
asio::async_connect(m_socket, endpoint_iterator,
[this](std::error_code ec, tcp::resolver::iterator) {
if (!ec) {
do_write();
}
});
}
void do_read_header()
{
m_socket.async_read_some(asio::buffer(m_databuffer, HEADER_LEN),
[this](std::error_code ec, std::size_t length) {
if (!ec) {
memcpy(&buf_waited_len, &m_databuffer[0], 4);
if (buf_waited_len == 0) {
m_socket.close();
return;
}
std::cout << "Header length waited: " << buf_waited_len << std::endl;
do_read_body();
}
else {
m_socket.close();
return;
}
do_read_body();
});
}
void do_read_body()
{
m_socket.async_read_some(asio::buffer(m_databuffer, buf_waited_len),
[this](std::error_code ec, std::size_t length) {
if (!ec) {
std::cout << "Length: " << length << ", Buffer: "
<< std::endl << "===========" << std::endl
<< &m_databuffer[0] << std::endl << "===========" << std::endl;
}
else {
m_socket.close();
return;
}
do_read_header();
});
}
void do_write()
{
char buf[4096 + 4];
memset(buf, 'A', sizeof(buf));
uint32_t size = 4096;
memcpy(&buf[0], &size, 4);
asio::async_write(m_socket, asio::buffer(buf, 4096 + 4),
[this](std::error_code ec, std::size_t /*length*/)
{
if (!ec) {
do_write();
}
else
{
m_socket.close();
}
});
}
tcp::socket m_socket;
uint32_t buf_waited_len = 0;
std::array<char, MAX_DATABUF_SIZE> m_databuffer;
asio::io_service &m_io_service;
};
class GameListener
{
public:
GameListener(asio::io_service &io_service, const tcp::endpoint &endpoint):
m_acceptor(io_service, endpoint),
m_socket(io_service)
{
do_accept();
}
private:
void do_accept()
{
m_acceptor.async_accept(m_socket, [this](std::error_code ec) {
if (!ec) {
std::make_shared<GameSession>(std::move(std::move(m_socket)))->start();
}
std::cout << "accept new client" << std::endl;
do_accept();
});
}
tcp::acceptor m_acceptor;
tcp::socket m_socket;
};
void run_server()
{
try {
std::cout << "Server starts..." << std::endl;
asio::io_service io_service;
tcp::endpoint endpoint(tcp::v6(), 34000);
GameListener gameListener_v6(io_service, endpoint);
io_service.run();
}
catch (std::exception &e) {
std::cerr << "Server Exception: " << e.what() << std::endl;
}
}
void run_client()
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
try {
std::cout << "Client starts..." << std::endl;
asio::io_service io_service;
tcp::resolver resolver(io_service);
auto endpoint_iterator = resolver.resolve({ "localhost", "34000" });
GameClient c(io_service, endpoint_iterator);
io_service.run();
}
catch (std::exception &e) {
std::cerr << "Client Exception: " << e.what() << std::endl;
}
}
int main()
{
//std::thread server(run_server);
std::thread client(run_client);
//server.join();
client.join();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment