본문 바로가기
-----ETC-----/C++ 네트워크 프로그래밍 시리즈

[C++ 네트워크 프로그래밍] Day 3: 소켓 프로그래밍 기초 (UDP)

by cogito21_cpp 2024. 8. 1.
반응형

UDP 소켓 프로그래밍

UDP(User Datagram Protocol)는 비연결형 프로토콜로, 신뢰성보다는 빠른 데이터 전송을 목적으로 합니다. UDP는 데이터의 순서나 무결성을 보장하지 않기 때문에, 주로 실시간 스트리밍, 게임 네트워크, 간단한 요청-응답 등의 용도로 사용됩니다.

 

UDP 소켓 프로그래밍의 주요 함수

소켓 생성

  • socket() 함수: 소켓을 생성합니다.
    • domain: 주소 체계 (예: AF_INET - IPv4)
    • type: 소켓 타입 (예: SOCK_DGRAM - UDP)
    • protocol: 프로토콜 (일반적으로 0으로 설정)
  • int socket(int domain, int type, int protocol);

서버 측 소켓 프로그래밍

  • bind() 함수: 소켓에 IP 주소와 포트 번호를 바인딩합니다.
  • int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • recvfrom() 함수: 데이터를 수신합니다.
  • ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
  • sendto() 함수: 데이터를 전송합니다.
  • ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

클라이언트 측 소켓 프로그래밍

  • sendto() 함수: 데이터를 전송합니다.
  • ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
  • recvfrom() 함수: 데이터를 수신합니다.
  • ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

UDP 서버 구현

UDP 서버 코드 예제

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

using boost::asio::ip::udp;

int main() {
    try {
        // io_context 객체 생성
        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 클라이언트 구현

UDP 클라이언트 코드 예제

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

using boost::asio::ip::udp;

int main() {
    try {
        // io_context 객체 생성
        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;
}

 

설명

위의 코드는 간단한 UDP 에코 서버와 클라이언트를 구현한 예제입니다. 클라이언트는 사용자가 입력한 메시지를 서버로 전송하고, 서버는 수신한 메시지를 다시 클라이언트로 전송합니다.

  • UDP 에코 서버:
    • 서버는 udp::socket을 사용하여 포트 12345에서 데이터그램을 수신합니다.
    • 클라이언트로부터 데이터를 수신한 후, 동일한 데이터를 다시 클라이언트로 전송합니다.
  • UDP 에코 클라이언트:
    • 클라이언트는 udp::socket을 사용하여 서버의 엔드포인트로 데이터그램을 전송합니다.
    • 서버로부터 에코된 메시지를 수신하여 출력합니다.

실습 문제

문제 1: 간단한 에코 서버와 클라이언트 작성하기

TCP 에코 서버와 클라이언트를 작성하여, 클라이언트가 보낸 메시지를 서버가 다시 클라이언트에게 보내도록 구현하세요.

 

해설:

UDP 에코 서버

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

using boost::asio::ip::udp;

int main() {
    try {
        // io_context 객체 생성
        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 {
        // io_context 객체 생성
        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;
}

 

이제 세 번째 날의 학습을 마쳤습니다. UDP 소켓 프로그래밍의 기본 개념과 구현 방법을 학습했습니다.

질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "비동기 소켓 프로그래밍"에 대해 학습하겠습니다.

반응형