session 부분임.
session 특징:
- TCP session. Server / Client 모두 다 사용.
- 접속하였을 때와 패킷을 받았을 때 콜백 호출. 나머지 필요하면 그때 새로운 콜백 추가.
- ReadBuffer 를 그냥 packet_parser 콜백에 넘기기 때문에, 더 좋은 성능을 이끌어 내고 싶으면
- packet_parser 콜백 받는 부분에서 버퍼를 복사한 후 다른 쓰레드로 넘겨서 처리해야 함.
- packet_parser 부분이 길어지게 되면 당연히 async_read 를 늦게 걸 수 밖에 없기 때문에 성능이 저하됨.
- 에러처리는 기본적인 것만 되어 있음.
session.h
#pragma once
#ifndef _SESSION_H_
#define _SESSION_H_
#include "structure.h"
#include
#include
using boost::asio::ip::tcp;
using namespace std;
class session;
typedef boost::shared_ptrsession_ptr;
typedef boost::functioncb_boost_func;
typedef bool (*cb_packet) (void* cb_class, packet_ptr p, session_ptr s);
typedef bool (*cb_connect) (void* cb_class, session_ptr s, const boost::system::error_code& error);
class session : public boost::enable_shared_from_this
{
private:
tcp::socket socket_;
data_buffer read_buffer_;
data_buffer write_buffer_;
bool authorized_;
void* cb_class_;
cb_packet parse_packet_;
public:
session(boost::asio::io_service& io_service) :
socket_(io_service), authorized_(0), cb_class_(0), parse_packet_(0)
{
}
virtual ~session() {;}
tcp::socket& socket() { return socket_; }
bool get_authorized() const { return authorized_; }
void set_authorized(bool value) { authorized_ = value; }
void start()
{
do_async_read();
}
void send_packet(packet_ptr packet)
{
// check a packet size
if(packet->body_length_ > max_body_size)
{
cerr << "\n -Error- packet size is too large : " << packet->body_length_ << "\n";
return;
}
do_async_write(packet);
}
void set_callback(void* cb_class, cb_packet cb_func)
{
cb_class_ = cb_class;
parse_packet_ = cb_func;
}
void do_async_read()
{
// read only header
boost::asio::async_read(socket_,
boost::asio::buffer(read_buffer_.data_.begin(), header_size),
boost::bind(&session::do_async_read_body,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
//socket_.async_read_some(
// boost::asio::buffer(read_buffer_.data_.begin(), max_packet_size),
// boost::bind(&session::handle_read,
// shared_from_this(),
// boost::asio::placeholders::error,
// boost::asio::placeholders::bytes_transferred)
// );
}
void do_async_read_body(const boost::system::error_code& error, size_t bytes_transferred)
{
if(error)
{
if(bytes_transferred == 0)
cerr << "\n -Close socket. \n";
else
cerr << "\n -Error- do_async_read_body (" << error.message() << ")\n";
// close this socket
this->socket_.close();
return;
}
packet_header header;
memcpy(&header, static_cast(read_buffer_.data_.begin()), header_size);
// read body
boost::asio::async_read(socket_,
boost::asio::buffer(&read_buffer_.data_[header_size], header.body_length_),
boost::bind(&session::handle_read,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
}
void do_async_write(packet_ptr packet)
{
memcpy((void*)&write_buffer_.data_[0], (void*)static_cast(packet.get()), header_size);
memcpy((void*)&write_buffer_.data_[header_size], (void*)packet->data_, packet->body_length_);
boost::asio::async_write(socket_,
boost::asio::buffer(write_buffer_.data_.begin(), header_size + packet->body_length_),
boost::bind(&session::handle_write,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
}
protected:
void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
if(error)
{
cerr << "\n -Error- handler_read (" << error.message() << ")\n";
// close this socket ?
return;
}
cout << "\nhandle_read : bytes_transferred " << bytes_transferred << " bytes" << endl;
if(bytes_transferred == 0)
{
// normal close.
return;
}
if(bytes_transferred > max_packet_size)
{
cerr << "\n -Error- handler_read : too many transferred bytes (" << bytes_transferred << ")\n";
return;
}
packet_header* header = reinterpret_cast(read_buffer_.data_.begin());
if(!header || header->body_length_ <= 0 || header->body_length_ > max_body_size)
{
assert(header);
cerr << "\n -Error- handler_read : abnormal error read buffer" << std::endl;
return;
}
packet_ptr packet(new packet);
packet->index_ = header->index_;
packet->body_length_ = header->body_length_;
packet->data_ = new char[packet->body_length_];
memcpy(packet->data_, (void*)&read_buffer_.data_[header_size], packet->body_length_);
// invoke a callback function
if(parse_packet_(cb_class_, packet, shared_from_this()) == false)
{
cerr << "\n -Error- handler_read : packet_parse returned false. socket closed." << std::endl;
socket_.close();
return;
}
// do an asynchronous read again
do_async_read();
}
void handle_write(const boost::system::error_code& error, size_t bytes_transferred)
{
#ifdef _DEBUG
cout << "\nhander_write bytes transferred : " << bytes_transferred << " bytes" << endl;
#endif
// do nothing.
}
};
#endif//_SESSION_H_
No comments:
Post a Comment