- 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 |