반응형
멀티스레드 서버 개발 (Boost.Asio)
멀티스레드 서버는 동시에 여러 클라이언트 요청을 처리할 수 있도록 설계된 서버입니다. 멀티스레드 서버를 사용하면 여러 클라이언트가 동시에 서버와 상호 작용할 수 있어 성능이 향상됩니다. Boost.Asio는 멀티스레드 프로그래밍을 지원하는 강력한 네트워크 프로그래밍 라이브러리입니다.
멀티스레드 서버의 주요 개념
- io_context: 비동기 작업을 관리하는 핵심 객체입니다. 여러 스레드에서 io_context를 공유하여 동시에 작업을 처리할 수 있습니다.
- strand: 멀티스레드 환경에서 안전하게 비동기 작업을 실행하기 위한 도구입니다. strand를 사용하면 동일한 io_context에서 실행되는 작업이 충돌 없이 실행됩니다.
- 스레드 풀: 여러 스레드를 생성하여 io_context의 작업을 병렬로 처리할 수 있습니다.
멀티스레드 서버 구현
Boost.Asio를 사용하여 멀티스레드 서버를 구현해 보겠습니다. 이 서버는 클라이언트의 연결을 수락하고, 데이터를 주고받을 수 있습니다.
멀티스레드 서버 코드 예제
AsyncMultiThreadServer.h
#ifndef ASYNCMULTITHREADSERVER_H
#define ASYNCMULTITHREADSERVER_H
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <thread>
#include <vector>
#include <memory>
#include <iostream>
namespace beast = boost::beast;
namespace net = boost::asio;
using tcp = net::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
public:
explicit Session(tcp::socket socket)
: socket_(std::move(socket)) {}
void run() {
do_read();
}
private:
void do_read() {
auto self = shared_from_this();
socket_.async_read_some(net::buffer(data_),
[this, self](beast::error_code ec, std::size_t length) {
if (!ec) {
do_write(length);
}
});
}
void do_write(std::size_t length) {
auto self = shared_from_this();
net::async_write(socket_, net::buffer(data_, length),
[this, self](beast::error_code ec, std::size_t /*length*/) {
if (!ec) {
do_read();
}
});
}
tcp::socket socket_;
char data_[1024];
};
class Listener : public std::enable_shared_from_this<Listener> {
public:
Listener(net::io_context& ioc, tcp::endpoint endpoint)
: acceptor_(ioc), socket_(ioc) {
beast::error_code ec;
acceptor_.open(endpoint.protocol(), ec);
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
acceptor_.set_option(net::socket_base::reuse_address(true), ec);
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
acceptor_.bind(endpoint, ec);
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
acceptor_.listen(net::socket_base::max_listen_connections, ec);
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
do_accept();
}
private:
void do_accept() {
acceptor_.async_accept(socket_,
[this](beast::error_code ec) {
if (!ec) {
std::make_shared<Session>(std::move(socket_))->run();
}
do_accept();
});
}
tcp::acceptor acceptor_;
tcp::socket socket_;
};
#endif // ASYNCMULTITHREADSERVER_H
main.cpp
#include <iostream>
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <memory>
#include <thread>
#include <vector>
#include "AsyncMultiThreadServer.h"
namespace net = boost::asio;
using tcp = net::ip::tcp;
int main() {
try {
auto const address = net::ip::make_address("0.0.0.0");
auto const port = static_cast<unsigned short>(std::atoi("12345"));
auto const threads = std::max<int>(1, std::thread::hardware_concurrency());
net::io_context ioc{threads};
std::make_shared<Listener>(ioc, tcp::endpoint{address, port})->run();
std::vector<std::thread> v;
v.reserve(threads - 1);
for (auto i = threads - 1; i > 0; --i) {
v.emplace_back([&ioc] {
ioc.run();
});
}
ioc.run();
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
설명
위의 코드는 Boost.Asio를 사용하여 멀티스레드 서버를 구현한 예제입니다. 이 서버는 클라이언트의 연결을 수락하고, 데이터를 주고받는 기능을 제공합니다.
- Session 클래스:
Session
클래스는 클라이언트와의 세션을 관리합니다. 클라이언트와 데이터를 주고받습니다.do_read()
함수는 클라이언트로부터 데이터를 비동기적으로 읽습니다.do_write()
함수는 클라이언트에게 데이터를 비동기적으로 씁니다.
- Listener 클래스:
Listener
클래스는 클라이언트의 연결을 수락합니다. TCP 수신자를 사용하여 연결을 수락하고, 새로운Session
객체를 생성합니다.do_accept()
함수는 비동기적으로 클라이언트의 연결을 수락합니다.
- main 함수:
main
함수는 io_context를 생성하고, 여러 스레드를 생성하여 io_context의 작업을 병렬로 처리합니다.- 각 스레드는
ioc.run()
을 호출하여 io_context의 작업을 실행합니다.
이제 열다섯 번째 날의 학습을 마쳤습니다. 멀티스레드 서버의 기본 개념과 Boost.Asio를 사용하여 간단한 멀티스레드 서버를 구현하는 방법을 학습했습니다.
질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "비동기 I/O와 이벤트 드리븐 프로그래밍"에 대해 학습하겠습니다.
반응형
'-----ETC----- > C++ 네트워크 프로그래밍 시리즈' 카테고리의 다른 글
[C++ 네트크 프로그래밍] Day 17: 네트워크 보안 기초 (SSL/TLS) (0) | 2024.08.01 |
---|---|
[C++ 네트워크 프로그래밍] Day 14: 웹 소켓 서버 개발 (0) | 2024.08.01 |
[C++ 네트워크 프로그래밍] Day 12: 웹 소켓 프로그래밍 기초 (0) | 2024.08.01 |
[C++ 네트워크 프로그래밍] Day 13: 웹 소켓 클라이언트 개발 (0) | 2024.08.01 |
[C++ 네트워크 프로그래밍] Day 10: HTTP 서버 개발 (Boost.Beast) (0) | 2024.08.01 |