boost asio example
// ./boost_1_81_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp
// ./boost_1_81_0/doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp
$ cd boost_1_81_0
$ ./bootstrap.sh
$ ./b2
The Boost C++ Libraries were successfully built!
The following directory should be added to compiler include paths:
/home/ljh/Downloads/boost_1_81_0
The following directory should be added to linker library paths:
/home/ljh/Downloads/boost_1_81_0/stage/lib
$
# or,
$ apt install libboost-dev
---
// src/Makefile
SUBDIRS = main # foo
all : $(SUBDIRS)
# main : foo
install : $(SUBDIRS)
define versioning # version soversion
$(MAKE) -C $@ soversion=lib$@.so.$(2)
@ cp $@/$@ $@/lib$@.so.$(1)
@ cd $@; ln -f -s lib$@.so.$(1) lib$@.so.$(2); cd ..
@ cd $@; ln -f -s lib$@.so.$(1) lib$@.so; cd ..
endef
# foo :
# $(call versioning,1.2.3,1.2) #,version,soversion
main :
$(MAKE) -C $@
# make -C src/ DESTDIR=~/foo install
install :
install -d "$(DESTDIR)/usr/local/bin"
# install -d "$(DESTDIR)/usr/local/lib"
install -m0755 main/main "$(DESTDIR)/usr/local/bin"
# install -m0755 foo/*.so foo/*.so.* "$(DESTDIR)/usr/local/lib"
clean :
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir $@; \
done
.PHONY : $(SUBDIRS) all clean install
---
// src/main/Makefile
# build shared library with -fPIC, -shared
CXXFLAGS = # -g -O3 -fPIC # CXXFLAGS for .cpp
CPPFLAGS = #-MMD -MP -I../foo
LDFLAGS = # -L../foo -Wl,-rpath,'$$ORIGIN/../foo' # -shared
LDLIBS = -lpthread
CC = $(CXX) # link with CXX for .cpp
CPPFLAGS += -I/home/ljh/Downloads/boost_1_81_0
LDFLAGS += -L/home/ljh/Downloads/boost_1_81_0/stage/lib
# make # NDEBUG=1
ifdef NDEBUG
CPPFLAGS += -DNDEBUG
CXXFLAGS += -O3 # .cpp
else
CXXFLAGS += -g # .cpp
LDFLAGS += -fsanitize=address
endif
all: server client
# target name is basename of one of the source files
# main : $(patsubst %.c,%.o,$(wildcard *.c)) # .cpp
server : $(patsubst %.cpp,%.o,server.cpp) # .cpp
client : $(patsubst %.cpp,%.o,client.cpp) # .cpp
-include *.d
clean : ; -rm -fr *.o *.d server client
.PHONY : clean
---
// src/main/server.cpp
// ./boost_1_81_0/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
#include <sanitizer/lsan_interface.h>
struct session
: public std::enable_shared_from_this<session>
{
session(boost::asio::ip::tcp::socket socket)
: socket(std::move(socket))
{ }
void start() {
start_read();
start_write();
}
void start_read() {
auto self(shared_from_this());
memset(input_data, 0, sizeof(input_data));
socket.async_read_some(
boost::asio::buffer(input_data, sizeof(input_data)),
[&, self](boost::system::error_code ec, std::size_t length) {
if (!ec) {
std::cout << input_data;
start_read();
} else {
std::cout << ec.message() << "\n";
}
}
);
}
void start_write() {
auto self(shared_from_this());
memset(output_data, 0, sizeof(output_data));
snprintf(output_data, sizeof(output_data) - 1,
"hello client %zu\n", cnt++);
boost::asio::async_write(
socket,
boost::asio::buffer(output_data, sizeof(input_data)),
[&, self](boost::system::error_code ec, std::size_t length)
{
if (!ec) {
// sleep(1); //test
start_write();
} else {
std::cout << ec.message() << "\n";
}
}
);
}
boost::asio::ip::tcp::socket socket;
enum { LEN = 1024 };
char input_data[LEN];
char output_data[LEN];
size_t cnt = 0;
};
struct server {
server(boost::asio::io_context& io_context, short port)
: acceptor(io_context, boost::asio::ip::tcp::endpoint(
boost::asio::ip::tcp::v4(), port))
{
std::cout << "Listen on port: " << port << " \n";
do_accept();
}
void do_accept() {
acceptor.async_accept(
[&](boost::system::error_code ec,
boost::asio::ip::tcp::socket socket)
{
if (!ec) {
std::cout << "Accept connection: "
<< socket.remote_endpoint() << "\n";
std::make_shared<session>(std::move(socket))->start();
} else {
std::cout << ec.message() << "\n";
}
do_accept();
}
);
}
boost::asio::ip::tcp::acceptor acceptor;
};
void handlerCont(int signum) {
printf("SIGCONT %d\n", signum);
#ifndef NDEBUG
__lsan_do_recoverable_leak_check();
#endif
}
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: server <port>\n";
return 1;
}
signal(SIGCONT, handlerCont); // $ man 7 signal
boost::asio::io_context io_context;
server s(io_context, std::atoi(argv[1]));
io_context.run();
return 0;
}
---
// src/main/client.cpp
// ./boost_1_81_0/doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/write.hpp>
#include <iostream>
#include <string>
#include <sanitizer/lsan_interface.h>
std::string client_tag; //test
struct session
: public std::enable_shared_from_this<session>
{
session(boost::asio::ip::tcp::socket socket)
: socket(std::move(socket))
{ }
void start() {
start_read();
start_write();
}
void start_read() {
auto self(shared_from_this());
memset(input_data, 0, sizeof(input_data));
socket.async_read_some(
boost::asio::buffer(input_data, sizeof(input_data)),
[&, self](boost::system::error_code ec, std::size_t length) {
if (!ec) {
std::cout << input_data;
start_read();
} else {
std::cout << ec.message() << "\n";
}
}
);
}
void start_write() {
auto self(shared_from_this());
memset(output_data, 0, sizeof(output_data));
snprintf(output_data, sizeof(output_data) - 1,
"hello server %s %zu\n", client_tag.c_str(), cnt++);
boost::asio::async_write(
socket,
boost::asio::buffer(output_data, sizeof(input_data)),
[&, self](boost::system::error_code ec, std::size_t length)
{
if (!ec) {
// sleep(1); //test
start_write();
} else {
std::cout << ec.message() << "\n";
}
}
);
}
boost::asio::ip::tcp::socket socket;
enum { LEN = 1024 };
char input_data[LEN];
char output_data[LEN];
size_t cnt = 0;
};
struct client {
client(boost::asio::io_context& io_context,
boost::asio::ip::tcp::resolver::results_type endpoints)
: socket(io_context), endpoints(endpoints)
{
do_connect(endpoints.begin());
}
void do_connect (
boost::asio::ip::tcp::resolver::results_type::iterator
endpoint_iter)
{
if (endpoint_iter != endpoints.end()) {
socket.async_connect(
endpoint_iter->endpoint(),
[&](const boost::system::error_code ec)
{
if (!socket.is_open()) {
std::cout << "Connect timed out\n";
do_connect(++endpoint_iter);
} else if (ec) {
std::cout << "Connect error: " << ec.message() << "\n";
socket.close();
} else {
std::cout << "Connected to " <<
socket.remote_endpoint() << "\n";
std::make_shared<session>(std::move(socket))->start();
}
}
);
}
}
boost::asio::ip::tcp::resolver::results_type endpoints;
boost::asio::ip::tcp::socket socket;
};
void handlerCont(int signum){
printf("SIGCONT %d\n", signum);
#ifndef NDEBUG
__lsan_do_recoverable_leak_check();
#endif
}
int main(int argc, char* argv[]) {
if (argc != 4) {
std::cerr << "Usage: client <host> <port> <tag>\n";
return 1;
}
signal(SIGCONT, handlerCont); // $ man 7 signal
client_tag = argv[3];
boost::asio::io_context io_context;
boost::asio::ip::tcp::resolver r(io_context);
client c(io_context, r.resolve(argv[1], argv[2]));
io_context.run();
return 0;
}