[Basic]Socket

👉🏻 기본적인 소켓에 대한 설명입니다.
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 % 

Leave a Reply