Asio:AsyncEcho
비동기 ECHO 서버 코드는 아래와 같다.
#include "config.h"
#include <iostream>
#include <algorithm>
#include <array>
#include <string>
#include <list>
#include <functional>
#include <boost/asio.hpp>
#define SERVER_IP "127.0.0.1"
#define PORT_NUMBER 9999
#define CHAR_BUFFER_SIZE 128
class Session
{
private:
boost::asio::ip::tcp::socket m_socket;
std::string m_writeMessage;
std::array<char, CHAR_BUFFER_SIZE> m_receiveBuffer;
public:
Session(boost::asio::io_service & io_service) :
m_socket(io_service)
{
}
boost::asio::ip::tcp::socket & Socket()
{
return m_socket;
}
void PostReceive()
{
m_receiveBuffer.fill(0);
m_socket.async_read_some(boost::asio::buffer(m_receiveBuffer),
std::bind(&Session::handle_receive, this, std::placeholders::_1,
std::placeholders::_2));
}
public:
void handle_write(boost::system::error_code const & error, size_t bytes_transferred)
{
}
void handle_receive(boost::system::error_code const & error, size_t bytes_transferred)
{
using namespace std;
if (error) {
if (error == boost::asio::error::eof) {
cout << "Disconnect client.\n";
} else {
cout << "error no: " << error.value() << ", error message: " << error.message()
<< endl;
}
} else {
string const recv_message = m_receiveBuffer.data();
cout << "Recv: " << recv_message << ", size: " << bytes_transferred << endl;
m_writeMessage = "Re: ";
m_writeMessage += recv_message;
m_socket.async_write_some(boost::asio::buffer(m_writeMessage),
std::bind(&Session::handle_write, this, std::placeholders::_1,
std::placeholders::_2));
PostReceive();
}
}
};
class TcpServer
{
private:
int m_seqNumber;
boost::asio::ip::tcp::acceptor m_acceptor;
Session * m_session;
public:
TcpServer(boost::asio::io_service & io_service) :
m_acceptor(io_service,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), PORT_NUMBER))
{
m_session = nullptr;
StartAccept();
}
virtual ~TcpServer()
{
if (m_session != nullptr) {
delete m_session;
}
}
public:
void StartAccept()
{
using namespace std;
cout << "Wait for client...\n";
m_session = new Session(m_acceptor.get_io_service());
m_acceptor.async_accept(m_session->Socket(),
std::bind(&TcpServer::handle_accept, this, m_session, std::placeholders::_1));
}
void handle_accept(Session * session, boost::system::error_code const & error)
{
using namespace std;
if (!error) {
cout << "Acept client.\n";
session->PostReceive();
}
}
};
int main(int argc, char ** argv)
{
using namespace std;
cout << "echo-server\n";
boost::asio::io_service io_service;
TcpServer server(io_service);
io_service.run();
cout << "END...\n";
return 0;
}
클라이언트 코드는 아래와 같다.
#include "config.h"
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#define SERVER_IP "127.0.0.1"
#define PORT_NUMBER 9999
#define CHAR_BUFFER_SIZE 128
class TcpClient
{
private:
boost::asio::io_service & m_io_service;
boost::asio::ip::tcp::socket m_socket;
int m_seq_number;
std::array<char, CHAR_BUFFER_SIZE> m_receiveBuffer;
std::string m_writeMessage;
public:
TcpClient(boost::asio::io_service & io_service) :
m_io_service(io_service), m_socket(io_service), m_seq_number(0)
{
}
virtual ~TcpClient()
{
}
public:
void Connect(boost::asio::ip::tcp::endpoint & endpoint)
{
m_socket.async_connect(endpoint,
std::bind(&TcpClient::handle_connect, this, std::placeholders::_1));
}
void PostWrite()
{
if (m_socket.is_open() == false) {
return;
}
if (m_seq_number > 7) {
m_socket.close();
return;
}
++m_seq_number;
std::cin >> m_writeMessage;
m_socket.async_write_some(boost::asio::buffer(m_writeMessage),
std::bind(&TcpClient::handle_write, this, std::placeholders::_1,
std::placeholders::_2));
PostReceive();
}
void PostReceive()
{
m_receiveBuffer.fill(0);
m_socket.async_read_some(boost::asio::buffer(m_receiveBuffer),
std::bind(&TcpClient::handle_receive, this, std::placeholders::_1,
std::placeholders::_2));
}
public:
void handle_connect(boost::system::error_code const & error)
{
using namespace std;
if (error) {
cout << "Connection fail." << error.value() << ", message: " << error.message() << endl;
} else {
cout << "Connection success.\n";
PostWrite();
}
}
void handle_write(boost::system::error_code const & error, size_t byte_transferred)
{
}
void handle_receive(boost::system::error_code const & error, size_t byte_transferred)
{
using namespace std;
if (error) {
if (error == boost::asio::error::eof) {
cout << "Disconnect server.\n";
} else {
cout << "error no: " << error.value() << ", error message: " << error.message()
<< endl;
}
} else {
string const recvMessage = m_receiveBuffer.data();
cout << "RecvMessage: " << recvMessage << ", size: " << byte_transferred << endl;
PostWrite();
}
}
};
int main(int argc, char ** argv)
{
using namespace std;
cout << "echo-client\n";
boost::asio::io_service io_service;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(SERVER_IP),
/* ** */PORT_NUMBER);
TcpClient client(io_service);
client.Connect(endpoint);
io_service.run();
cout << "END...\n";
return 0;
}
MinGW를 사용한 컴파일은 아래와 같이 진행한다.
g++ -o async-echo-server.o -c async-echo-server.cpp -std=c++11 -DWINDOWS
g++ -o async-echo-server async-echo-server.o -lboost_system -lWS2_32 -lmswsock
g++ -o async-echo-client.o -c async-echo-client.cpp -std=c++11 -DWINDOWS
g++ -o async-echo-client async-echo-client.o -lboost_system -lWS2_32 -lmswsock