호타리 2025. 5. 29. 18:38

2025.05.29

 

 

sercer.c

// server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9000

static void kill_port_users(int port) {
    char cmd[64];
    snprintf(cmd, sizeof(cmd), "fuser -k %d/tcp 2>/dev/null", port);
    system(cmd);
}

int main(void) {
    int server_sock, client_sock;
    struct sockaddr_in saddr, caddr;
    socklen_t addr_len = sizeof(caddr);
    char buf[1024];
    ssize_t r;
    int opt = 1;

    // 기존 포트 점유 프로세스 제거
    kill_port_users(PORT);

    // 1) socket()
    if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return 1;
    }

    // 2) SO_REUSEADDR
    if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("setsockopt");
        close(server_sock);
        return 1;
    }

    // 3) bind()
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family      = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port        = htons(PORT);
    if (bind(server_sock, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
        perror("bind");
        close(server_sock);
        return 1;
    }

    // 4) listen()
    if (listen(server_sock, 2) < 0) {
        perror("listen");
        close(server_sock);
        return 1;
    }
    printf("▶ Server listening on port %d …\n", PORT);

    // 5) accept()
    if ((client_sock = accept(server_sock, (struct sockaddr*)&caddr, &addr_len)) < 0) {
        perror("accept");
        close(server_sock);
        return 1;
    }

    // 6) 원격 엔드포인트 정보 출력
    printf("▶ Client connected!\n");
    printf("   RemoteEP_ADDR  = %s\n", inet_ntoa(caddr.sin_addr));
    printf("   RemoteEP_port  = %d\n", ntohs(caddr.sin_port));

    // 7) read loop
    while ((r = read(client_sock, buf, sizeof(buf)-1)) > 0) {
        buf[r] = '\0';
        printf("> %s (%zd bytes)\n", buf, r);
    }
    if (r < 0) perror("read");

    close(client_sock);
    close(server_sock);
    return 0;
}

 

client.c

// client.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9000

int main(int argc, char *argv[]) {
    int sock;
    struct sockaddr_in saddr;
    char buf[500];
    ssize_t w;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <server_ip>\n", argv[0]);
        return 1;
    }
    const char *server_ip = argv[1];

    // 1) 소켓 생성
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return 1;
    }

    // 2) 서버 주소 세팅
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port   = htons(PORT);
    if (inet_aton(server_ip, &saddr.sin_addr) == 0) {
        fprintf(stderr, "Invalid IP address: %s\n", server_ip);
        close(sock);
        return 1;
    }

    // 3) 서버에 연결
    if (connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
        perror("connect");
        close(sock);
        return 1;
    }

    // 4) 연결 정보 출력
    printf("▶ Connected to %s:%d\n", server_ip, PORT);
    printf("   Server_ADDR  = %s\n", inet_ntoa(saddr.sin_addr));
    printf("   Server_PORT  = %d\n", ntohs(saddr.sin_port));

    // 5) stdin에서 한 줄씩 읽어서 서버로 전송 (“> ” 프롬프트 추가)
    while (1) {
        printf("> ");              // 프롬프트
        fflush(stdout);            // 바로 출력되도록 플러시

        if (!fgets(buf, sizeof(buf), stdin))
            break;                 // EOF 또는 에러 시 종료

        size_t len = strlen(buf);
        if (len > 0 && buf[len-1] == '\n')
            buf[len-1] = '\0';     // 개행 제거
        if (buf[0] == '\0')
            continue;              // 빈 줄은 건너뛰기

        w = write(sock, buf, strlen(buf));
        if (w < 0) {
            perror("write");
            break;
        }
    }

    close(sock);
    return 0;
}