์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

๐Ÿ”ง Boost.Asio ํŒจํ‚ท ์ˆ˜์‹  ์ตœ์ ํ™”: ์‹œ์Šคํ…œ ์ฝœ ์ตœ์†Œํ™” ๊ตฌํ˜„

denny 2025. 5. 22. 07:41

 

๐Ÿ“Œ ๋ฐฐ๊ฒฝ ์„ค๋ช…

MMORPG ๋˜๋Š” ์‹ค์‹œ๊ฐ„ ๊ฒŒ์ž„ ์„œ๋ฒ„์—์„œ๋Š” ์ˆ˜๋งŽ์€ ๋„คํŠธ์›Œํฌ ํŒจํ‚ท์„ ์ˆ˜์‹ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹์œผ๋กœ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ํ—ค๋” → ๋ฐ”๋”” ์ˆœ์„œ๋กœ ์ฝ์œผ๋ฉฐ, ๊ฐ๊ฐ์˜ async_read()๋Š” ์‹œ์Šคํ…œ ์ฝœ์„ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

async_read(socket, buffer(header_buf), ...);  // ์‹œ์Šคํ…œ ์ฝœ 1
async_read(socket, buffer(body_buf), ...);    // ์‹œ์Šคํ…œ ์ฝœ 2

์ด ๋ฐฉ์‹์€ ๋‚ฎ์€ ์ฒ˜๋ฆฌ ํšจ์œจ, ๋†’์€ CPU ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โœ… ์ตœ์ ํ™” ์ „๋žต

  • ์‹œ์Šคํ…œ ์ฝœ 1ํšŒ: socket.async_read_some()์œผ๋กœ ํ•œ๊บผ๋ฒˆ์— ์ˆ˜์‹ 
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์—์„œ ํŒŒ์‹ฑ: ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฒ„ํผ์— ์ €์žฅํ•˜๊ณ , ๋‚ด๋ถ€์—์„œ ํ—ค๋”/๋ฐ”๋”” ๊ตฌ๋ถ„
  • ๋ฒ„ํผ ๊ตฌ์กฐ: boost::asio::streambuf ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ring buffer ์‚ฌ์šฉ

๐Ÿ“˜ ํ”„๋กœํ† ์ฝœ ๊ฐ€์ •

  • ๊ณ ์ •๋œ 2๋ฐ”์ดํŠธ ํ—ค๋” (๋ฐ”๋”” ๊ธธ์ด ์ •๋ณด ํฌํ•จ)
  • [Header(2 bytes)][Body(N bytes)]

โœ… ์ตœ์ ํ™” ์˜ˆ์ œ ์ฝ”๋“œ

#include <boost/asio.hpp>
#include <iostream>
#include <vector>
#include <deque>

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

class PacketReceiver {
public:
    PacketReceiver(boost::asio::io_context& io_context)
        : socket_(io_context), stream_buf_() {}

    tcp::socket& socket() { return socket_; }

    void start() {
        do_read();
    }

private:
    static constexpr size_t HEADER_SIZE = 2;

    tcp::socket socket_;
    boost::asio::streambuf stream_buf_;

    void do_read() {
        socket_.async_read_some(stream_buf_.prepare(1024),
            [this](boost::system::error_code ec, std::size_t bytes_transferred) {
                if (!ec) {
                    stream_buf_.commit(bytes_transferred);
                    process_packets();
                    do_read(); // ๊ณ„์† ์ˆ˜์‹ 
                } else {
                    std::cerr << "Receive failed: " << ec.message() << "\n";
                }
            });
    }

    void process_packets() {
        while (true) {
            if (stream_buf_.size() < HEADER_SIZE)
                return; // ํ—ค๋” ๋ถ€์กฑ

            std::istream is(&stream_buf_);
            is.unsetf(std::ios::skipws); // binary-safe ์ฝ๊ธฐ

            std::istream::pos_type pos = is.tellg();
            uint16_t body_len;
            is.read(reinterpret_cast<char*>(&body_len), HEADER_SIZE);

            if (stream_buf_.size() < HEADER_SIZE + body_len) {
                // ๋ฐ”๋””๊นŒ์ง€ ๋„์ฐฉ ์•ˆ ํ–ˆ์œผ๋ฉด ๋‹ค์‹œ ๋’ค๋กœ
                is.seekg(pos);
                return;
            }

            std::vector<char> body(body_len);
            is.read(body.data(), body_len);

            handle_packet(body);
        }
    }

    void handle_packet(const std::vector<char>& body) {
        // ์‹ค์ œ ํŒจํ‚ท ์ฒ˜๋ฆฌ ๋กœ์ง
        std::cout << "[Packet Received] Size = " << body.size() << "\n";
    }
};

๐Ÿง  ํ•ต์‹ฌ ์š”์  ์ •๋ฆฌ

ํ•ญ๋ชฉ ์„ค๋ช…

๐Ÿ“ฅ ๋‹จ์ผ ์‹œ์Šคํ…œ ์ฝœ async_read_some() 1ํšŒ๋กœ ์—ฌ๋Ÿฌ ํŒจํ‚ท ์ˆ˜์‹  ๊ฐ€๋Šฅ
๐Ÿง  ํ—ค๋”/๋ฐ”๋”” ๊ตฌ๋ถ„์€ ์ˆ˜์‹  ํ›„ ํŒŒ์‹ฑ ๋ฒ„ํผ์—์„œ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜์—ฌ ์„ฑ๋Šฅ ํ–ฅ์ƒ
๐Ÿ’พ ๋ฒ„ํผ ๊ตฌ์กฐ ์œ ์—ฐ streambuf, ring buffer ๋“ฑ ๋‹ค์–‘ํ•˜๊ฒŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅ
๐Ÿš€ ํšจ์œจ์ ์ธ ํŒจํ‚ท ์ฒ˜๋ฆฌ ์žฆ์€ read() ํ˜ธ์ถœ ์—†์ด๋„ ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

๐Ÿ“ˆ ์„ฑ๋Šฅ ์ด์ 

์ธก๋ฉด ๊ฐœ์„  ํšจ๊ณผ

๐Ÿ” ์‹œ์Šคํ…œ ์ฝœ ์•ฝ 50% ์ด์ƒ ๊ฐ์†Œ (ํ—ค๋”+๋ฐ”๋”” ๋ถ„๋ฆฌ ์ˆ˜์‹  ๋Œ€๋น„)
๐Ÿงฉ ์บ์‹œ ํšจ์œจ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์—ฐ์†์„ฑ ํ™•๋ณด
โš™๏ธ CPU ์‚ฌ์šฉ๋Ÿ‰ ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ๋ณ‘๋ชฉ ์ตœ์†Œํ™”
๐ŸŒ ๋Œ€๋Ÿ‰ ํด๋ผ์ด์–ธํŠธ ์ฒ˜๋ฆฌ MMORPG ์„œ๋ฒ„ ๋“ฑ ๊ณ ์„ฑ๋Šฅ ์š”๊ตฌ ์ƒํ™ฉ์— ์ ํ•ฉ

โœ… ์ถ”๊ฐ€ ํŒ

  • boost::asio::mutable_buffer๋ฅผ ํ™œ์šฉํ•œ ์ปค์Šคํ…€ ๋ฒ„ํผ ๊ด€๋ฆฌ๋„ ๊ฐ€๋Šฅ
  • tcp::no_delay ์˜ต์…˜ ํ™œ์„ฑํ™”ํ•˜์—ฌ Nagle ๋น„ํ™œ์„ฑํ™”
  • ๋ง ๋ฒ„ํผ ๊ธฐ๋ฐ˜ ํŒจํ‚ท ์ˆ˜์‹ ๊ธฐ๋กœ ํ™•์žฅ ์‹œ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋“œ ์ฒ˜๋ฆฌ์™€๋„ ๊ถํ•ฉ์ด ์ข‹์Œ

ํ•„์š”ํ•˜์‹œ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ™•์žฅ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค:

  • ์‚ฌ์šฉ์ž ์ •์˜ ๋ง ๋ฒ„ํผ ๊ตฌ์กฐ ๊ธฐ๋ฐ˜ ์ˆ˜์‹ ๊ธฐ ์˜ˆ์ œ
  • async_write()๋ฅผ ํ†ตํ•œ ํŒจํ‚ท ์ „์†ก ๊ตฌ์กฐ
  • ๊ณ ์ • ํ—ค๋”/๊ฐ€๋ณ€ ๋ฐ”๋”” ๊ตฌ์กฐ์˜ ์ถ”์ƒํ™” ํด๋ž˜์Šค ์„ค๊ณ„