지난번에 토마토 소스를 부으려다가 까르보나라 소스를 부어버린 비운의 파스타.
그래서 다시 만들어서 먹어봤다.
익히는 시간은 조금 줄이고, 올리브 유에 볶는 시간을 늘렸더니
맛이 더 좋아진 듯 하다. 스파게티도 이렇게 한번 해봐야겠다.
재료 : 양파, 마늘, 버섯, 파스타, 베이컨, 녹색피망, 토마토소스, 케챱, 모챠렐라 치즈
#pragma once
#ifndef _ASIO_CLIENT_H_
#define _ASIO_CLIENT_H_
#include "session.h"
class asio_client
{
private:
boost::asio::io_service& io_service_;
tcp::resolver::iterator endpoint_iterator_;
session_ptr session_;
boost::thread t_;
void* cb_class_;
cb_connect cb_connect_;
bool started_;
public:
asio_client(boost::asio::io_service& io_service, tcp::resolver::iterator endpoint_iterator) :
io_service_(io_service), endpoint_iterator_(endpoint_iterator),
cb_class_(0), cb_connect_(0),
started_(0)
{
session_ptr new_session(new session(io_service));
session_ = new_session;
//connect();
}
void connect()
{
tcp::endpoint endpoint = *endpoint_iterator_;
session_->socket().async_connect(endpoint,
boost::bind(&asio_client::handle_connect,
this,
boost::asio::placeholders::error,
++endpoint_iterator_)
);
}
void connect_blocking()
{
boost::system::error_code error;
session_->socket().connect(*endpoint_iterator_, error);
if(error)
{
cerr << "Error! failed to connect to a patch server : << " << started_ =" true;" started_ ="="" t_ =" boost::thread(boost::bind(&boost::asio::io_service::run," started_ ="="" cb_class_ =" cb_class;" cb_connect_ =" f_connect;">set_callback(cb_class, f_parser);
}
protected:
void handle_connect(const boost::system::error_code& error, tcp::resolver::iterator endpoint_iterator)
{
if(error)
{
cerr << "\n -Error- failed to connect to a patch server : << " <<>do_async_read();
}
void do_close()
{
cout << "Close socket" <<>socket().close();
}
};
typedef boost::shared_ptrasio_client_ptr;
#endif//_ASIO_CLIENT_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_
#include
#include
#include
#include
struct packet_header
{
unsigned short index_;
unsigned short body_length_;
packet_header() : index_(0), body_length_(0) {}
};
struct packet : public packet_header
{
char* data_;
packet() : data_(0) {}
~packet() { if(data_) delete [] data_; }
};
const int header_size = (int)sizeof(packet_header);
const int max_body_size = 1024; // If you need more size, just edit this!!!
const int max_packet_size = header_size + max_body_size;
struct data_buffer
{
boost::arraydata_;
};
typedef boost::shared_ptrpacket_header_ptr;
typedef boost::shared_ptrpacket_ptr;
typedef boost::shared_ptrdata_buffer_ptr;
namespace Protocol
{
public struct packet_header
{
public System.UInt16 index_;
public System.UInt16 body_length_;
}
public struct packet
{
public packet_header h_;
public System.Byte[] data_;
}
public class packet_size
{
public static readonly int header_size;
public static readonly int max_body_size;
public static readonly int max_packet_size;
static packet_size()
{
header_size = Marshal.SizeOf(typeof(packet_header));
max_body_size = 1024;
max_packet_size = header_size + max_body_size;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using Protocol;
namespace network_lib
{
public class packet_args : EventArgs
{
private packet p_;
public packet_args(packet p)
{
p_ = p;
}
public packet data
{
get { return p_; }
}
}
public delegate void packet_event(object sender, packet_args p);
class packet_parse
{
public event packet_event e_;
public void do_packet_parse(packet p)
{
if (e_ != null)
e_(this, new packet_args(p));
}
}
public class client_session
{
#region Private Variables
private string ip_;
private string port_;
private Socket client_socket_;
private packet read_packet_;
private Byte[] read_buffer_;
private Byte[] write_buffer_;
private IAsyncResult result_;
private AsyncCallback cb_async_read_body_;
private AsyncCallback cb_handle_read_;
private AsyncCallback cb_handle_write_;
private packet_parse event_packet_;
#endregion
#region Constructors
public client_session()
{
init();
}
public client_session(string ip, string port)
{
ip_ = ip;
port_ = port;
init();
}
#endregion
#region Properties
public string IP
{
get { return ip_; }
set { ip_ = value; }
}
public string Port
{
get { return port_; }
set { port_ = value; }
}
public bool connected
{
get { return (client_socket_ != null) ? client_socket_.Connected: false; }
}
#endregion
#region Public Methods
public void add_packet_event(packet_event h)
{
event_packet_.e_ += h;
}
public void connect()
{
try
{
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(ip_), System.Convert.ToUInt16(port_));
client_socket_ = new Socket(System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Stream,
System.Net.Sockets.ProtocolType.Tcp);
client_socket_.Connect(ip);
if (client_socket_.Connected)
do_async_read();
}
catch (SystemException se)
{
MessageBox.Show(se.Message);
}
}
public void disconnect()
{
if (connected)
client_socket_.Disconnect(false);
}
public void do_async_read()
{
try
{
// do_async_read_head
result_ = client_socket_.BeginReceive(read_buffer_,
0,
packet_size.header_size,
SocketFlags.None,
cb_async_read_body_,
read_buffer_);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
public void do_async_write(packet p)
{
try
{
packet_header heaer = p.h_;
System.Byte[] buffer = raw_serialize_ex(heaer);
buffer.CopyTo(write_buffer_, 0);
p.data_.CopyTo(write_buffer_, packet_size.header_size);
// do_async_write
result_ = client_socket_.BeginSend(write_buffer_,
0,
packet_size.header_size + p.h_.body_length_,
SocketFlags.None,
cb_handle_write_,
write_buffer_);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
// copied from group.google.com
public object raw_deserialize_ex(byte[] rawdatas, Type anytype)
{
int rawsize = Marshal.SizeOf(anytype);
if (rawsize > rawdatas.Length)
return null;
GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
IntPtr buffer = handle.AddrOfPinnedObject();
object retobj = Marshal.PtrToStructure(buffer, anytype);
handle.Free();
return retobj;
}
// copied from group.google.com
public byte[] raw_serialize_ex(object anything)
{
int rawsize = Marshal.SizeOf(anything);
byte[] rawdatas = new byte[rawsize];
GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
IntPtr buffer = handle.AddrOfPinnedObject();
Marshal.StructureToPtr(anything, buffer, false);
handle.Free();
return rawdatas;
}
#endregion
#region Private Methods
private void init()
{
client_socket_ = null;
cb_async_read_body_ = new AsyncCallback(do_async_read_body);
cb_handle_read_ = new AsyncCallback(cb_handle_read);
cb_handle_write_ = new AsyncCallback(cb_handle_write);
read_packet_.data_ = new System.Byte[packet_size.max_body_size];
read_buffer_ = new System.Byte[packet_size.max_packet_size];
write_buffer_ = new System.Byte[packet_size.max_packet_size];
event_packet_ = new packet_parse();
}
private void do_async_read_body(IAsyncResult r)
{
try
{
int bytes_transferred = client_socket_.EndReceive(r);
if (bytes_transferred == 0)
{
// normal close
return;
}
if (bytes_transferred != packet_size.header_size)
{
MessageBox.Show(" !Error - invalid received header size : " + bytes_transferred);
return;
}
packet_header header;
System.Byte[] header_buffer = new System.Byte[packet_size.header_size];
System.Buffer.BlockCopy(read_buffer_, 0, header_buffer, 0, packet_size.header_size);
header = (packet_header)raw_deserialize_ex(header_buffer, typeof(packet_header));
read_packet_.h_.index_ = header.index_;
read_packet_.h_.body_length_ = header.body_length_;
// do_async_read_body
result_ = client_socket_.BeginReceive(read_buffer_,
packet_size.header_size,
header.body_length_,
SocketFlags.None,
cb_handle_read_,
read_buffer_);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void cb_handle_read(IAsyncResult r)
{
try
{
int bytes_transferred = client_socket_.EndReceive(r);
if (bytes_transferred > packet_size.max_body_size)
{
MessageBox.Show(" !Error - invalid received body size : " + bytes_transferred);
return;
}
System.Buffer.BlockCopy(read_buffer_, packet_size.header_size, read_packet_.data_, 0, bytes_transferred);
// parse packet
event_packet_.do_packet_parse(read_packet_);
// do_async_read
do_async_read();
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void cb_handle_write(IAsyncResult r)
{
int bytes_transferred = client_socket_.EndSend(r);
string msg = "packet has been sent. bytes : " + bytes_transferred + "\n";
}
#endregion
}
}