ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C++ 네트워크 프로그래밍과 소켓 통신
    c++ 2025. 2. 4. 23:13
    728x90

    1. 네트워크 프로그래밍이란?

    네트워크 프로그래밍은 컴퓨터 간의 데이터 전송을 위해 프로그래밍하는 기술입니다. 이를 통해 클라이언트와 서버 간의 통신을 구현할 수 있습니다.

    (1) 소켓(Socket)이란?

    • 소켓은 네트워크를 통해 데이터를 송수신하기 위한 양 끝단의 인터페이스입니다.
    • C++에서는 주로 BSD 소켓 API를 사용하여 네트워크 통신을 구현합니다.

    (2) 클라이언트-서버 모델

    1. 서버(Server): 클라이언트의 요청을 기다리고 응답하는 역할
    2. 클라이언트(Client): 서버에 요청을 보내고 응답을 받는 역할

    2. C++에서 소켓 프로그래밍 준비하기

    C++에서 소켓 프로그래밍을 위해 다음 헤더 파일을 포함해야 합니다.

    #include <iostream>
    #include <cstring>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    • <sys/socket.h>: 소켓 관련 함수 정의
    • <arpa/inet.h>: IP 주소 변환 함수
    • <unistd.h>: 시스템 호출 함수 (close() 등)

    3. TCP 소켓 프로그래밍: 서버 구현

    (1) TCP 서버 기본 코드

    #include <iostream>
    #include <cstring>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    using namespace std;
    
    int main() {
        int server_fd, new_socket;
        struct sockaddr_in address;
        int opt = 1;
        int addrlen = sizeof(address);
        char buffer[1024] = {0};
        const char* message = "Hello from server!";
    
        // 소켓 생성
        server_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_fd == 0) {
            perror("소켓 생성 실패");
            exit(EXIT_FAILURE);
        }
    
        // 소켓 옵션 설정
        setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
    
        // 주소 및 포트 설정
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(8080);
    
        // 소켓에 주소 바인딩
        if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
            perror("바인딩 실패");
            exit(EXIT_FAILURE);
        }
    
        // 연결 대기 상태로 전환
        if (listen(server_fd, 3) < 0) {
            perror("리스닝 실패");
            exit(EXIT_FAILURE);
        }
    
        cout << "서버가 클라이언트 요청을 기다리고 있습니다..." << endl;
    
        // 클라이언트 연결 수락
        new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
        if (new_socket < 0) {
            perror("연결 수락 실패");
            exit(EXIT_FAILURE);
        }
    
        // 클라이언트로부터 메시지 수신
        read(new_socket, buffer, 1024);
        cout << "클라이언트로부터 받은 메시지: " << buffer << endl;
    
        // 클라이언트로 메시지 전송
        send(new_socket, message, strlen(message), 0);
        cout << "메시지를 클라이언트로 전송했습니다." << endl;
    
        // 소켓 종료
        close(new_socket);
        close(server_fd);
    
        return 0;
    }

    (2) 코드 설명

    • socket(): 소켓 생성
    • bind(): 소켓에 IP 주소와 포트 번호 연결
    • listen(): 클라이언트 연결 대기
    • accept(): 클라이언트 연결 수락
    • read(): 클라이언트로부터 데이터 수신
    • send(): 클라이언트로 데이터 전송

    (3) 서버 실행

    g++ server.cpp -o server
    ./server

    4. TCP 소켓 프로그래밍: 클라이언트 구현

    (1) TCP 클라이언트 기본 코드

    #include <iostream>
    #include <cstring>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    using namespace std;
    
    int main() {
        int sock = 0;
        struct sockaddr_in serv_addr;
        char buffer[1024] = {0};
    
        // 소켓 생성
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("소켓 생성 실패");
            return -1;
        }
    
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(8080);
    
        // IP 주소 변환
        if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
            perror("주소 변환 실패");
            return -1;
        }
    
        // 서버에 연결 요청
        if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
            perror("연결 실패");
            return -1;
        }
    
        // 서버로 메시지 전송
        const char* message = "Hello from client!";
        send(sock, message, strlen(message), 0);
        cout << "메시지를 서버로 전송했습니다." << endl;
    
        // 서버로부터 응답 수신
        read(sock, buffer, 1024);
        cout << "서버로부터 받은 메시지: " << buffer << endl;
    
        // 소켓 종료
        close(sock);
    
        return 0;
    }

    (2) 클라이언트 실행

    g++ client.cpp -o client
    ./client

    5. 서버-클라이언트 통신 결과

    1. 서버 실행 결과:
    서버가 클라이언트 요청을 기다리고 있습니다...
    클라이언트로부터 받은 메시지: Hello from client!
    메시지를 클라이언트로 전송했습니다.
    1. 클라이언트 실행 결과:
    메시지를 서버로 전송했습니다.
    서버로부터 받은 메시지: Hello from server!

    6. 멀티 클라이언트 지원 서버 구현

    여러 클라이언트의 요청을 처리하기 위해 멀티스레딩 서버를 구현할 수 있습니다.

    #include <iostream>
    #include <thread>
    #include <vector>
    #include <cstring>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    using namespace std;
    
    void handleClient(int client_socket) {
        char buffer[1024] = {0};
        read(client_socket, buffer, 1024);
        cout << "클라이언트로부터 받은 메시지: " << buffer << endl;
    
        const char* message = "서버 응답: 요청을 처리했습니다.";
        send(client_socket, message, strlen(message), 0);
    
        close(client_socket);
    }
    
    int main() {
        int server_fd, new_socket;
        struct sockaddr_in address;
        int addrlen = sizeof(address);
    
        server_fd = socket(AF_INET, SOCK_STREAM, 0);
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(8080);
    
        bind(server_fd, (struct sockaddr*)&address, sizeof(address));
        listen(server_fd, 5);
    
        cout << "서버가 여러 클라이언트 요청을 기다리고 있습니다..." << endl;
    
        while (true) {
            new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
            thread t(handleClient, new_socket);
            t.detach();  // 독립적인 스레드로 실행
        }
    
        close(server_fd);
        return 0;
    }

     

    728x90
Designed by Tistory.