네트워크 프로토콜 기초
네트워크 프로토콜은 네트워크 상에서 데이터를 주고받는 규칙을 정의한 것입니다. 프로토콜은 데이터의 형식, 전송 방식, 오류 처리 등을 규정합니다. 네트워크 통신의 대부분은 여러 프로토콜의 조합으로 이루어집니다.
OSI 7계층 모델
OSI(Open Systems Interconnection) 모델은 네트워크 통신을 7개의 계층으로 나눈 모델입니다. 각 계층은 특정한 기능을 담당하며, 서로 독립적으로 동작합니다.
- 물리 계층 (Physical Layer): 물리적인 매체를 통해 데이터를 전송합니다. (예: 케이블, 전파)
- 데이터 링크 계층 (Data Link Layer): 인접한 네트워크 노드 간의 데이터 전송을 담당합니다. (예: Ethernet, Wi-Fi)
- 네트워크 계층 (Network Layer): 네트워크 간의 데이터 전송을 담당합니다. (예: IP)
- 전송 계층 (Transport Layer): 종단 간의 데이터 전송을 담당합니다. (예: TCP, UDP)
- 세션 계층 (Session Layer): 통신 세션을 설정하고 관리합니다. (예: NetBIOS, PPTP)
- 표현 계층 (Presentation Layer): 데이터의 인코딩과 디코딩을 담당합니다. (예: SSL/TLS, JPEG)
- 응용 계층 (Application Layer): 응용 프로그램 간의 데이터 교환을 담당합니다. (예: HTTP, FTP, SMTP)
주요 프로토콜
TCP (Transmission Control Protocol)
- 특징: 신뢰성 있는 연결 지향형 프로토콜입니다. 데이터의 순서와 무결성을 보장합니다.
- 사용 예: 웹 브라우징(HTTP/HTTPS), 이메일(POP3/IMAP), 파일 전송(FTP)
UDP (User Datagram Protocol)
- 특징: 신뢰성이 없고 비연결형 프로토콜입니다. 빠른 데이터 전송을 목적으로 합니다.
- 사용 예: 실시간 스트리밍, 온라인 게임, VoIP
HTTP (HyperText Transfer Protocol)
- 특징: 웹에서 데이터를 주고받기 위한 응용 계층 프로토콜입니다. 텍스트 기반 프로토콜로, 클라이언트-서버 모델을 따릅니다.
- 사용 예: 웹 페이지 요청과 응답
HTTPS (HTTP Secure)
- 특징: HTTP에 SSL/TLS 암호화를 추가하여 보안을 강화한 프로토콜입니다.
- 사용 예: 보안이 필요한 웹 페이지 요청과 응답
FTP (File Transfer Protocol)
- 특징: 파일 전송을 위한 응용 계층 프로토콜입니다.
- 사용 예: 서버 간의 파일 전송, 파일 다운로드/업로드
프로토콜 분석 도구
네트워크 프로토콜을 분석하고 디버깅하기 위해 다양한 도구를 사용할 수 있습니다. 대표적인 도구로는 Wireshark가 있습니다.
Wireshark
- Wireshark: 네트워크 트래픽을 캡처하고 분석할 수 있는 도구입니다. 다양한 프로토콜을 지원하며, 네트워크 문제를 디버깅하는 데 유용합니다.
네트워크 프로그래밍에서의 프로토콜 사용
네트워크 프로그래밍에서는 주로 TCP와 UDP 프로토콜을 사용하여 데이터를 전송합니다. 다음은 TCP와 UDP를 사용한 간단한 예제입니다.
TCP 클라이언트-서버 예제
TCP 서버
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main() {
try {
boost::asio::io_context io_context;
// TCP 수신자 생성, 포트 12345에서 수신 대기
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 12345));
std::cout << "TCP 서버가 포트 12345에서 대기 중입니다..." << std::endl;
while (true) {
// 새로운 소켓 객체 생성
tcp::socket socket(io_context);
// 클라이언트 연결 수락
acceptor.accept(socket);
// 클라이언트에게 보낼 메시지
std::string message = "Hello from TCP server!";
boost::system::error_code ignored_error;
// 클라이언트에게 메시지 전송
boost::asio::write(socket, boost::asio::buffer(message), ignored_error);
}
} catch (std::exception& e) {
std::cerr << "예외 발생: " << e.what() << std::endl;
}
return 0;
}
TCP 클라이언트
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main() {
try {
boost::asio::io_context io_context;
// TCP 리졸버 생성
tcp::resolver resolver(io_context);
tcp::resolver::results_type endpoints = resolver.resolve("127.0.0.1", "12345");
// TCP 소켓 생성
tcp::socket socket(io_context);
// 서버에 연결 요청
boost::asio::connect(socket, endpoints);
// 서버로부터 메시지 수신
boost::asio::streambuf buf;
boost::asio::read_until(socket, buf, "\n");
std::istream is(&buf);
std::string message;
std::getline(is, message);
std::cout << "서버로부터 수신한 메시지: " << message << std::endl;
} catch (std::exception& e) {
std::cerr << "예외 발생: " << e.what() << std::endl;
}
return 0;
}
UDP 클라이언트-서버 예제
UDP 서버
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
int main() {
try {
boost::asio::io_context io_context;
// UDP 수신자 생성, 포트 12345에서 수신 대기
udp::socket socket(io_context, udp::endpoint(udp::v4(), 12345));
std::cout << "UDP 서버가 포트 12345에서 대기 중입니다..." << std::endl;
while (true) {
char data[1024];
udp::endpoint sender_endpoint;
boost::system::error_code error;
// 클라이언트로부터 데이터 수신
size_t length = socket.receive_from(boost::asio::buffer(data), sender_endpoint, 0, error);
if (error && error != boost::asio::error::message_size) {
throw boost::system::system_error(error);
}
std::cout << "수신한 메시지: " << std::string(data, length) << std::endl;
// 클라이언트에게 수신한 메시지 그대로 전송 (에코)
socket.send_to(boost::asio::buffer(data, length), sender_endpoint, 0, error);
}
} catch (std::exception& e) {
std::cerr << "예외 발생: " << e.what() << std::endl;
}
return 0;
}
UDP 클라이언트
#include <iostream>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
int main() {
try {
boost::asio::io_context io_context;
// UDP 소켓 생성
udp::socket socket(io_context);
// 서버의 엔드포인트 생성
udp::endpoint server_endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 12345);
// 사용자로부터 입력받은 메시지를 서버로 전송하고, 에코된 메시지를 수신
std::string message;
while (std::getline(std::cin, message)) {
message += "\n";
boost::system::error_code error;
// 서버로 메시지 전송
socket.send_to(boost::asio::buffer(message), server_endpoint, 0, error);
char data[1024];
udp::endpoint sender_endpoint;
// 서버로부터 에코된 메시지 수신
size_t length = socket.receive_from(boost::asio::buffer(data), sender_endpoint, 0, error);
std::cout << "서버로부터 에코된 메시지: " << std::string(data, length) << std::endl;
}
} catch (std::exception& e) {
std::cerr << "예외 발생: " << e.what() << std::endl;
}
return 0;
}
설명
위의 코드는 TCP와 UDP 프로토콜을 사용하여 간단한 서버와 클라이언트를 구현한 예제입니다. TCP는 신뢰성 있는 연결 지향형 프로토콜로
, 클라이언트와 서버 간의 데이터 전송을 처리합니다. UDP는 신뢰성이 없는 비연결형 프로토콜로, 빠른 데이터 전송을 처리합니다.
- TCP 서버:
- 서버는
tcp::acceptor
를 사용하여 클라이언트의 연결을 수락하고, 데이터를 송수신합니다.
- 서버는
- TCP 클라이언트:
- 클라이언트는
tcp::resolver
와tcp::socket
을 사용하여 서버에 연결하고, 데이터를 수신합니다.
- 클라이언트는
- UDP 서버:
- 서버는
udp::socket
을 사용하여 클라이언트의 데이터를 수신하고, 에코합니다.
- 서버는
- UDP 클라이언트:
- 클라이언트는
udp::socket
을 사용하여 서버에 데이터를 전송하고, 에코된 데이터를 수신합니다.
- 클라이언트는
이제 여섯 번째 날의 학습을 마쳤습니다. 네트워크 프로토콜의 기본 개념과 TCP 및 UDP 프로토콜을 사용한 네트워크 프로그래밍을 학습했습니다.
질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "네트워크 디버깅 기법"에 대해 학습하겠습니다.
'-----ETC----- > C++ 네트워크 프로그래밍 시리즈' 카테고리의 다른 글
[C++ 네트워크 프로그래밍] Day 8: HTTP 프로토콜 개요 (0) | 2024.08.01 |
---|---|
[C++ 네트워크 프로그래밍] Day 5: 네트워크 데이터 직렬화 (0) | 2024.08.01 |
[C++ 네트워크 프로그래밍] Day 3: 소켓 프로그래밍 기초 (UDP) (0) | 2024.08.01 |
[C++ 네트워크 프로그래밍] Day 4: 비동기 소켓 프로그래밍 (0) | 2024.08.01 |
[C++ 네트워크 프로그래밍] Day 2: 소켓 프로그래밍 기초 (TCP) (0) | 2024.08.01 |