👉🏻 기본적인 소켓에 대한 설명입니다.
This is an explanation of basic sockets.
👉🏻 Echo Server는 클라이언트에서 보낸 메세지를 서버가 다시 클라이언트로 보내는 간단한 코드입니다.
Echo Server is simple code that sends a message sent from a client back to the client.
👉🏻 Thread Server는 아주 기본적인 채팅 서버 구조를 가지고 있습니다.
Thread Server has a very basic chat server structure.
👉🏻 Echo Server
✔️ Server.cpp
#include <iostream>
#include <sys/socket.h> // 소켓 API / Socket API
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
int main() {
// 소켓 생성,0은 프로토콜 자동 선택
// // Create socket, 0 for automatic protocol selection
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in address;
address.sin_family = AF_INET; // IPv4
address.sin_addr.s_addr = INADDR_ANY; // 모든 IP 허용 / Allow all IPs
address.sin_port = htons(5080); // 포트 8080 / Port 8080
bind(server_fd, (struct sockaddr*)&address, sizeof(address)); // 주소 바인딩 / Address Binding
listen(server_fd, 3); // 접속 대기 / Waiting for connection
std::cout << "listening..." << std::endl;
int new_socket = accept(server_fd, nullptr, nullptr); // 연결 수락 / Accept Connection
char buffer[1024] = {0};
read(new_socket, buffer, 1024); // 데이터 수신 / Receive Data
std::cout << "수신된 메시지 / Received Message: " << buffer << std::endl;
const char* hello = "Hello from server";
send(new_socket, hello, strlen(hello), 0); // 응답 전송 / Send Response
close(new_socket);
close(server_fd);
return 0;
}
✔️ Client.cpp
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0); // 소켓 생성 / create socket
sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5080);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); // 서버 IP 설정 / Server IP settings
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); // 서버 접속 / server connection
const char* message = "Hello from client";
send(sock, message, strlen(message), 0); // 메세지 전송 / Send Message
char buffer[1024] = {0};
read(sock, buffer, 1024); // 서버 응답 수신 / Receive Server Response
std::cout << "서버 응답 / Server Response: " << buffer << std::endl;
close(sock); // 소켓 종료 / Close Socket
return 0;
}
✔️ 컴파일 / Compiling
g++ Server.cpp -o server -std=c++17
g++ Client.cpp -o client -std=c++17
✔️ 실행 / Run
./server
./client
✔️ 결과 / Result
# server
MacBookAir echo % ./server
listening...
수신된 메시지 / Received Message: Hello from client
# client
MacBookAir echo % ./client
서버 응답 / Server Response: Hello from server
👉🏻 ThreadServer
✔️threadServer.cpp
#include <iostream>
#include <thread> // 스레드 헤더 / thread header
#include <vector>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
// 클라이언트와 통신하기 위한 함수
// A function to communicate with the client
void handle_client(int client_socket) {
char buffer[1024];
while (true) {
// 버퍼를 모두 0으로 초기화해서 기존 쓰레기 값 지우기
// Initialize buffer to all 0s to clear existing garbage values
memset(buffer, 0, 1024);
ssize_t valread = read(client_socket, buffer, 1024);
if (valread <= 0) {
std::cout << "클라이언트 접속 종료 / Client connection terminated " << std::endl;
break;
}
std::cout << "수신된 메시지 / Received message: " << buffer << std::endl;
send(client_socket, buffer, valread, 0); // send
}
close(client_socket);
}
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
// 포트가 이미 사용 중이어도 즉시 재사용 가능하게 설정
// Configure port to be immediately reusable even if it is already in use
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(5080);
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("Bind failed"); // 에러 내용 출력 / Error details output
return 1;
}
if (listen(server_fd, 5) < 0) {
perror("Listen failed");
return 1;
}
std::cout << "서버 정상 시작, 접속 대기 중 / Server started normally, waiting for connection ..." << std::endl;
while (true) {
int client_sock = accept(server_fd, nullptr, nullptr);
if (client_sock < 0) {
perror("Accept failed");
continue;
}
std::cout << "새 클라이언트 연결됨 / New Client Connected: " << client_sock << ")" << std::endl;
std::thread(handle_client, client_sock).detach();
}
return 0;
}
✔️Client.cpp
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0); // 소켓 생성 / create socket
sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5080);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); // 서버 IP 설정 / Set Server IP
connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); // 서버 접속 / Connect to Server
// const char* message = "Hello from client";
// send(sock, message, strlen(message), 0); // 메시지 전송
// char buffer[1024] = {0};
// read(sock, buffer, 1024); // 서버 응답 수신
// std::cout << "서버 응답: " << buffer << std::endl;
while (true) {
std::string msg;
std::cout << "보낼 메시지 (종료는 quit): ";
std::getline(std::cin, msg); // 키보드 입력 받기 / Receiving keyboard input
// quit가 입력되면... / When quit is entered...
if (msg == "quit") break;
send(sock, msg.c_str(), msg.length(), 0); // 메세지를 서버로 전송 / Send message to server
char buffer[1024] = {0};
int valread = read(sock, buffer, 1024); // 서버 응답 대기 / Waiting for server response
if (valread <= 0) {
std::cout << "서버와의 연결이 끊겼습니다. / Server connection closed." << std::endl;
break;
}
std::cout << "서버 응답 / Server response:: " << buffer << std::endl;
}
close(sock); // 소켓 종료 / Socket close
return 0;
}
✔️ 컴파일 / Compiling
g++ threadServer.cpp -o server -std=c++17 -pthread
g++ Client.cpp -o client -std=c++17
✔️ 실행 / Run
./server
./clinet
✔️결과 / Result
# server
MacBookAir thread % ./server
서버 정상 시작, 접속 대기 중 / Server started normally, waiting for connection ...
새 클라이언트 연결됨 / New Client Connected: 4)
수신된 메시지 / Received message: hello
수신된 메시지 / Received message: 안녕하세요
수신된 메시지 / Received message: 8
클라이언트 접속 종료 / Client connection terminated
#client
MacBookAir thread % ./client
보낼 메시지 / Message to send (종료/Quit: quit): hello
서버 응답 / Server response:: hello
보낼 메시지 / Message to send (종료/Quit: quit): 안녕하세요
서버 응답 / Server response:: 안녕하세요
보낼 메시지 / Message to send (종료/Quit: quit): 8
서버 응답 / Server response:: 8
보낼 메시지 / Message to send (종료/Quit: quit): quit
MacBookAir thread %