- 메세지를 한번 주고 받고 세션을 종료하는 클라이언트 소켓
- boost::asio 라이브러리 사용 (boost 의 date_time, thread, system 컴파일 필요)
- boost::asio::deadline_timer 를 이용하여 timeout 기능 구현 
- 비동시 소켓으로 구현한 동기 소켓(?)



#pragma once

#include <algorithm>
using namespace std;

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

using boost::asio::ip::tcp;


struct IsEOF_Basic
{
bool operator()(const std::string &)
{
return true;
}
};



template <class Ty = IsEOF_Basic>
class ClientSocket 
{
public:
ClientSocket() : socket_(io_service_), timeout_(io_service_), nResponse_(0) {}

~ClientSocket() 
{
Close();
}

bool Connect(const string &sIP, const string &sPort) 
{
bool bResult = false;

tcp::resolver resolver(io_service_);
tcp::resolver::query query(tcp::v4(), sIP, sPort);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;

boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpoint_iterator != end)
{
socket_.close();
socket_.connect(*endpoint_iterator++, error);
}

if (!error) {
bResult = true;
}
return bResult;
}

void Send(const string &s, const int nTimeout = 5)
{
copy(s.begin(), s.end(), szBuff);

socket_.async_write_some(boost::asio::buffer(szBuff, s.length()),
boost::bind(&ClientSocket::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

timeout_.expires_from_now(boost::posix_time::seconds(nTimeout));
timeout_.async_wait(boost::bind(&ClientSocket::Timeout, this));

handle_read_wait();
}

int WaitForResponse()
{
socket_.io_service().reset();

while (socket_.io_service().run_one()) 
{
if (nResponse_) break;
}

return nResponse_;
}

void Close()
{
socket_.close();
}

std::string GetReadBuffer()
{
return sReadBuff_;
}

enum { TIMEOUT = -1, READY = 0, SUCCESS = 1 };

private:
void Timeout()
{
nResponse_ = TIMEOUT;
}

void handle_read_wait() 
{
socket_.async_read_some(boost::asio::buffer(szBuff, BUFF_SIZE),
boost::bind(&ClientSocket::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

nResponse_ = READY;
}

void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
if (error) {
Close();
return;
}

sReadBuff_.append(szBuff, szBuff + bytes_transferred);

if (IsEOF(sReadBuff_)) {
nResponse_ = SUCCESS;
}
else {
handle_read_wait();
}
}

void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
{
if (error) {
Close();
return;
}
}

private:
boost::asio::io_service io_service_;

boost::asio::deadline_timer timeout_;
tcp::socket socket_;
std::string sReadBuff_;
volatile int nResponse_;

Ty IsEOF;
enum { BUFF_SIZE = 8192};
char szBuff[BUFF_SIZE];
};

int SendPacket (
LPCSTR strIP, LPCSTR strPort, int nTimeoutSecond, LPCSTR szMessage, LPSTR szRetMessage)
{
int nResult = -2;

try {
typedef ClientSocket<> ClientSocketType;
ClientSocketType socket;

if (!socket.Connect(strIP, strPort)) {
throw -1;
}

if (nTimeoutSecond == 0) nTimeoutSecond = 5;

socket.Send(szMessage, nTimeoutSecond);
int nResponse = socket.WaitForResponse();

if (nResponse == ClientSocketType::TIMEOUT) {
throw 0;
}

if (nResponse == ClientSocketType::SUCCESS) {
std::string s = socket.GetReadBuffer();
std::copy(s.begin(), s.end(), szRetMessage);

nResult = s.size();
}
}
catch (int nErr) {
nResult = nErr;
}
catch (...) {}

return nResult;
}



'Dev > C++' 카테고리의 다른 글

[C++11] Variadic template  (0) 2014.11.02
boost 설치  (0) 2013.11.20
이미지 변환 모듈 (모바일용, GDI+)  (0) 2010.06.22
C++0x, RValue Reference  (0) 2009.05.27
C++0x Lambda  (0) 2009.05.20
http://sourceforge.net/projects/asio/

asio is a cross-platform C++ library for network and low-level I/O programming that provides developers with a consistent asynchronous model using a modern C++ approach.


asio 는 클로스 플랫폼은 지원하는 네트워크 라이브러리이다

ACE와는 비교도 안되게 가볍고 C++ 헤더로만 이루어져 있어 별도의 라이브러리 컴파일 과정이 필요없다.
그리고 각 플랫폼에 맞는 동기/비동기 모델을 하나의 인터페이스로 구현을 하여 유연성있는 네트워크 프로그램을 제공을 한다

boost 1.35부터 포함되어 있어 boost 라이브러리를 통해서 사용가능하고 직접 다운받아 stand alone 으로도  사용 가능하다


Download 쪽 항목을 보면 asio-tr2 라고 하는 패키지가 보이는데,
C++ tr2의 네트워크 라이브러리에 대한 제안서로 보인다.

개인적으로 tr2에 정의되어 있는 네트워크 라이브러리의 C++ 구현 인터페이스가 무지 궁금하지만,
asio 를 채택하는것도 그리 나쁜 선택은 아니라고 판단된다.


ps.
tr2의 내용중에 XML, HTML, Networking 같은 경우는 boost와 같이 C++ 계에서 주도적(?)으로
사용되는 것이 없어서 어떤 것들이 채택(혹은 구현)될지 궁금하다.

tr2의 주 내용
Unicode
XML and HTML
Networking
Usability for novices and occasional programmers


'Dev > C++' 카테고리의 다른 글

C++ Refactoring  (0) 2009.04.14
An Overview of the Coming C++ (C++0x) Standard  (0) 2008.12.29
C++ 0x - Herb Sutter의 블로그 글  (0) 2008.07.29
C++ 0x  (0) 2008.05.09
memory pooling - code  (0) 2008.05.01

+ Recent posts