Code: Select all
struct header
{
int size;
int id;
//..
};
struct body : public header
{
//....
};
아래와 같은 구조와 비슷할거라고 생각됩니다.(실제 돌아가는 코드는 당연히 아니며, 구조만 봐주세요.. )
Code: Select all
::socket layer
wait_recv()
{
buffer_info.buf = buffer;
buffer_info.len = max_buffer;
recv(socket, buffer, buffer_info, ....);
}
complete_recv(socket, async_result)
{
queue.enqueue(async_result.buffer, async_result.len);
wait_recv();
}
::application layer
while( queue.peek(header) == complete )
{
if( queue.peek(body) == complete )
{
queue.dequeue(message);
dispatch(message);
}
}
Code: Select all
wait_header_recv()
{
buffer_info.buf = buffer;
buffer_info.len = header_size;
recv(socket, buffer, buffer_info, ....);
}
wait_body_recv()
{
buffer_info.buf = buffer;
buffer_info.len = header.bodysize;
recv(socket, buffer, buffer_info, ....);
}
wait_recv()
{
if( recv_header == true )
wait_header_recv();
else
wait_body_recv();
}
complete_recv(socket, async_result)
{
async_result.buffer, async_result.len);
if( recv_header )
{
if( message.verify_header(async_result.buffer, async_result.len) == ok )
{
recv_header = false;
wait_recv()
}
else
.. wait_remain_header;
}
else
{
if( message.verify_body(async_result.buffer, async_result.len) == ok )
{
dispatch(message);
recv_header = true;
wait_recv()
}
else
.. wait_remain_body;
}
}
(물론 실제코드는 위와 같지는 않습니다. 제가 임의의 의사코드 비슷하게 만든겁니다...)
저 구조를 보고, 별도의 큐처리는 없어지고, 구조가 간결해 지는 대신, 성능상의 이슈가 있지 않겠는냐고 물었더니, 지금까지 문제 없이 잘쓰고 있었다고 합니다.(거의 십만 단위의 유저의 트랜젝션을 감당하는 서버에서 직접 사용되고 있고 잘 돌아 간다고 합니다(connection이 "십만"은 아닙니다 ) )
그래서 조금은 찜찜하지만, 그냥 넘어갔다가, 최근 boost::asio를 보고 있는데, chat sample코드의 구조가 위와 같네요.
실제 예제는 아래와 같습니다.
Code: Select all
void handle_read_header(const boost::system::error_code& error)
{
if (!error && read_msg_.decode_header())
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
boost::bind(&chat_session::handle_read_body, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
room_.leave(shared_from_this());
}
}
void handle_read_body(const boost::system::error_code& error)
{
if (!error)
{
room_.deliver(read_msg_);
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
boost::bind(&chat_session::handle_read_header, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
room_.leave(shared_from_this());
}
}
좀 정신없게 얘기한거 같지만, 여기서 문제
위와 같은 구조로 서버단 패킷을 처리 하면, 생길수 있는 문제는 어떤게 있을가요?
또는 실제 위와 같은 방식으로 패킷처리를 하고 계시는 분들이 계시면, 그 분들의 의견도 들어보고 싶습니다.
감사합니다.