티스토리 뷰
728x90
IOCP, Boost.Asio, epoll 예제
1. IOCP (Windows)
플랫폼: Windows
설명: IOCP는 Windows에서 제공하는 비동기 I/O 처리 메커니즘으로, 고성능 네트워크 서버를 구축할 때 사용됩니다.
예제 코드:
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <thread>
#include <vector>
#pragma comment(lib, "Ws2_32.lib")
struct ClientContext {
OVERLAPPED overlapped;
SOCKET socket;
char buffer[1024];
};
void workerThread(HANDLE iocpHandle) {
DWORD bytesTransferred;
ULONG_PTR completionKey;
LPOVERLAPPED overlapped;
while (true) {
BOOL result = GetQueuedCompletionStatus(
iocpHandle, &bytesTransferred, &completionKey, &overlapped, INFINITE);
if (!result || bytesTransferred == 0) {
std::cerr << "클라이언트가 연결을 종료했습니다." << std::endl;
continue;
}
auto* context = reinterpret_cast<ClientContext*>(completionKey);
std::cout << "받은 메시지: " << context->buffer << std::endl;
WSABUF wsabuf{bytesTransferred, context->buffer};
DWORD sent;
WSASend(context->socket, &wsabuf, 1, &sent, 0, &context->overlapped, nullptr);
}
}
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serverAddr{};
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(8080);
bind(serverSocket, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr));
listen(serverSocket, SOMAXCONN);
HANDLE iocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i) {
threads.emplace_back(workerThread, iocpHandle);
}
while (true) {
SOCKET clientSocket = accept(serverSocket, nullptr, nullptr);
auto* context = new ClientContext{};
context->socket = clientSocket;
CreateIoCompletionPort(reinterpret_cast<HANDLE>(clientSocket), iocpHandle,
reinterpret_cast<ULONG_PTR>(context), 0);
WSARecv(clientSocket, nullptr, 0, nullptr, nullptr, &context->overlapped, nullptr);
}
for (auto& t : threads) {
t.join();
}
closesocket(serverSocket);
WSACleanup();
return 0;
}
2. Boost.Asio (크로스 플랫폼)
플랫폼: Windows, Linux, macOS
설명: Boost.Asio는 플랫폼에 구애받지 않고 네트워크 및 비동기 I/O 처리를 쉽게 구현할 수 있는 라이브러리입니다.
예제 코드:
#include <boost/asio.hpp>
#include <iostream>
#include <memory>
using boost::asio::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
public:
explicit Session(tcp::socket socket) : socket_(std::move(socket)) {}
void start() {
doRead();
}
private:
tcp::socket socket_;
char buffer_[1024];
void doRead() {
auto self(shared_from_this());
socket_.async_read_some(
boost::asio::buffer(buffer_),
[this, self](boost::system::error_code ec, std::size_t length) {
if (!ec) {
doWrite(length);
}
});
}
void doWrite(std::size_t length) {
auto self(shared_from_this());
boost::asio::async_write(
socket_, boost::asio::buffer(buffer_, length),
[this, self](boost::system::error_code ec, std::size_t /*length*/) {
if (!ec) {
doRead();
}
});
}
};
class Server {
public:
Server(boost::asio::io_context& io_context, short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) {
doAccept();
}
private:
tcp::acceptor acceptor_;
void doAccept() {
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket) {
if (!ec) {
std::make_shared<Session>(std::move(socket))->start();
}
doAccept();
});
}
};
int main() {
try {
boost::asio::io_context io_context;
Server server(io_context, 8080);
io_context.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
3. epoll (Linux)
플랫폼: Linux
설명: epoll은 Linux에서 대규모 파일 디스크립터를 효율적으로 관리하는 이벤트 기반 I/O 메커니즘입니다.
예제 코드:
#include <sys/epoll.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(8080);
bind(server_fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
listen(server_fd, SOMAXCONN);
int epoll_fd = epoll_create1(0);
epoll_event event{}, events[10];
event.events = EPOLLIN;
event.data.fd = server_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event);
while (true) {
int n = epoll_wait(epoll_fd, events, 10, -1);
for (int i = 0; i < n; ++i) {
if (events[i].data.fd == server_fd) {
int client_fd = accept(server_fd, nullptr, nullptr);
event.events = EPOLLIN;
event.data.fd = client_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event);
} else {
char buffer[1024];
ssize_t bytes = read(events[i].data.fd, buffer, sizeof(buffer));
if (bytes > 0) {
write(events[i].data.fd, buffer, bytes); // 에코
} else {
close(events[i].data.fd);
}
}
}
}
close(server_fd);
return 0;
}
IOCP, Boost.Asio, epoll 예제
요약
기술 | 플랫폼 | 특징 | 장점 | 단점 |
---|---|---|---|---|
IOCP | Windows | 비동기 완료 기반 I/O 처리 | 수십만 동시 연결 처리 가능 | Windows 전용 |
Boost.Asio | 크로스 플랫폼 | 고수준 비동기 I/O | 이식성과 유연성 | 초기 러닝 커브 높음 |
epoll | Linux | 이벤트 기반 I/O | CPU 및 메모리 효율적 | Linux 전용 |
IOCP
플랫폼: Windows
빌드 방법:
- Visual Studio에서 프로젝트 생성
#include <winsock2.h>
와#include <windows.h>
추가- Ws2_32.lib 라이브러리를 프로젝트에 링크
실행 방법: Visual Studio에서 빌드 후 실행.
// Visual Studio 명령줄 빌드 예제:
cl /EHsc /DWIN32 iocp_server.cpp /link Ws2_32.lib
Boost.Asio
플랫폼: 크로스 플랫폼 (Windows, Linux, macOS)
빌드 방법:
- Boost 라이브러리 설치
- g++ 또는 Visual Studio로 빌드
Linux/Mac:
g++ -std=c++17 asio_server.cpp -o asio_server -lboost_system
Windows: Visual Studio에서 Boost 포함 설정 후 빌드.
실행 방법: 빌드된 실행 파일을 실행.
epoll
플랫폼: Linux
빌드 방법:
- Linux에서 g++로 컴파일
g++ -std=c++17 epoll_server.cpp -o epoll_server
실행 방법: 터미널에서 실행:
./epoll_server
결론
- IOCP: Windows에서 최고 성능의 네트워크 서버를 구축할 때 적합.
- Boost.Asio: 크로스 플랫폼 네트워크 애플리케이션 개발 시 추천.
- epoll: Linux 환경에서 대규모 네트워크 처리를 필요로 할 때 사용.
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 블루버블
- OpenSource
- ip
- 암호화
- 스쿠버 다이빙
- DLL
- PowerShell
- 윈도우
- Windows
- CMake
- 스쿠버다이빙
- C++
- script
- C
- 외돌개
- C#.NET
- 서귀포블루버블
- 블루버블다이빙팀
- 패턴
- C# 고급 기술
- Build
- 티스토리챌린지
- 현포다이브
- Linux
- 성산블루버블
- 블루버블다이브팀
- 울릉도
- 서귀포
- 제주도
- C#
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함
250x250