-
C++ 네트워크 프로그래밍과 소켓 통신c++ 2025. 2. 4. 23:13728x90
1. 네트워크 프로그래밍이란?
네트워크 프로그래밍은 컴퓨터 간의 데이터 전송을 위해 프로그래밍하는 기술입니다. 이를 통해 클라이언트와 서버 간의 통신을 구현할 수 있습니다.
(1) 소켓(Socket)이란?
- 소켓은 네트워크를 통해 데이터를 송수신하기 위한 양 끝단의 인터페이스입니다.
- C++에서는 주로 BSD 소켓 API를 사용하여 네트워크 통신을 구현합니다.
(2) 클라이언트-서버 모델
- 서버(Server): 클라이언트의 요청을 기다리고 응답하는 역할
- 클라이언트(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. 서버-클라이언트 통신 결과
- 서버 실행 결과:
서버가 클라이언트 요청을 기다리고 있습니다... 클라이언트로부터 받은 메시지: Hello from client! 메시지를 클라이언트로 전송했습니다.
- 클라이언트 실행 결과:
메시지를 서버로 전송했습니다. 서버로부터 받은 메시지: 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'c++' 카테고리의 다른 글
C++ 구조체 vs 클래스: 차이점과 올바른 활용법 (0) 2025.02.24 Modern C++ (0) 2025.02.06 C++ 멀티스레딩 프로그래밍과 동기화 기법 (0) 2025.02.03 C++ 표준 템플릿 라이브러리(STL)와 스마트 포인터 (0) 2025.02.03 C++ 객체 지향 프로그래밍: 연산자 오버로딩과 템플릿 (0) 2025.02.02