본문 바로가기
Computer Science/UNIX & Linux

[UNIX/Linux] ep11-3+) TCP 소켓 프로그래밍 실습

by 클레어몬트 2024. 12. 10.

ex1. 서버에 접속한 클라이언트에 관한 정보를 돌려주는 서비스 프로그램을 작성하라. 되돌려줄 정보는 호스트명, IP주소, 포트 번호이다.

struct infor_type {

    char host[256];

    char addr[20];

    int port;

}

 

struct infor_type msg;

 

** client

recv(sd, (char*)&msg, sizeof(msg), 0);

 

** server

struct hostent* hp;

 

hp = gethostbyaddr((char*)&cli.sin_addr.s_addr, 4, AF_INET);

sprintf(msg.host, “%s”, hp->h_name);

sprintf(msg.addr, “%s”, inet_ntoa(cli.sin_addr);

msg.port = cli.sin_port;

 

 

(ex1_server.c)

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PORTNUM 9000 	

struct infor_type {
    char host[256];
    char addr[20];
    int port;
};

int main() {
    char buf[256];
    struct sockaddr_in sin, cli;
    struct hostent* hp;
    struct in_addr in;
    struct infor_type msg;
    int sd, ns, clientlen = sizeof(cli);
   
    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset((char*)&sin, '\0', sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORTNUM);
    sin.sin_addr.s_addr = inet_addr("203.250.148.46");

    if (bind(sd, (struct sockaddr *)&sin, sizeof(sin))) {
        perror("bind");
        exit(1);
    }

    if (listen(sd, 5)) {
        perror("listen");
        exit(1);
    }

    if ((ns = accept(sd, (struct sockaddr*)&cli, &clientlen)) == -1) {
        perror("accept");
        exit(1);
    }
     
    hp = gethostbyaddr((char*)&cli.sin_addr.s_addr, 4, AF_INET);
    sprintf(msg.host, "%s", hp->h_name);
    sprintf(msg.addr, "%s", inet_ntoa(cli.sin_addr));
    msg.port = cli.sin_port;

    if (send(ns, (char*)&msg, sizeof(msg), 0) == -1) {
        perror("send");
        exit(1);
    }
    close(ns);
    close(sd);

    return 0;
}

 

(ex1_client.c)

#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PORTNUM 9000

struct infor_type {
    char host[256];
    char addr[20];
    int port;
};

int main() {
    int sd;
    char buf[256];
    struct sockaddr_in sin;
    struct infor_type msg;
   
    memset((char*)&sin, '\0', sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORTNUM);
    sin.sin_addr.s_addr = inet_addr("203.250.148.46");

    if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    if(connect(sd, (struct sockaddr*)&sin, sizeof(sin))) {
        perror("bind");
        exit(1);
    }

    if(recv(sd, (char*)&msg, sizeof(msg), 0) == -1) {
        perror("recv");
        exit(1);
    }
    close(sd);

    printf("From Server - Host Name : %s\n", msg.host);
    printf("From Server - IP Address : %s\n", msg.addr);
    printf("From Server - Port Number : %d\n", ntohs(sin.sin_port));

    return 0;
}

당연하지만, 서버를 먼저 켜두어야 한다

 

 

 

ex2. TCP/IP 프로토콜을 이용해 1:1 대화가 가능하도록 프로그램을 작성하라. 한 시스템 안에서 동작하도록 유닉스 도메인 소켓을 사용한다.

 

(ex2_server.c)

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SOCKET_NAME "hbsocket1" 

int main() {
    char buf[64];
    struct sockaddr_un ser, cli;
    int sd, nsd, len, clen;
   
    unlink(SOCKET_NAME);

    if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset((char*)&ser, 0, sizeof(struct sockaddr_un));
    ser.sun_family = AF_UNIX;
    strcpy(ser.sun_path, SOCKET_NAME);
    len = sizeof(ser.sun_family) + strlen(ser.sun_path);
    
    if (bind(sd, (struct sockaddr*)&ser, len)) {
        perror("bind");
        exit(1);
    }

    if (listen(sd, 5) < 0) {
        perror("listen");
        exit(1);
    }

    printf("Waiting ...\n");
    if ((nsd = accept(sd, (struct sockaddr*)&cli, &clen)) == -1) {
        perror("accept");
        exit(1);
    }

    while(1) {
        memset(buf, '\0', sizeof(buf));
        if (recv(nsd, buf, sizeof(buf), 0) == -1) {
            perror("recv");
            exit(1);
        }
        printf("** From Client : %s\n", buf);

        printf("** To Client : ");
        memset(buf, '\0', sizeof(buf));
        fgets(buf, sizeof(buf), stdin);
        if (send(nsd, buf, strlen(buf) + 1, 0) == -1) {
            perror("send");
            exit(1);
        }

        if (!strcmp(buf, "quit")) {
            break;
        }
    }
    close(nsd);
    close(sd);

    return 0;
}

 

(ex2_client.c)

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SOCKET_NAME "hbsocket1" 

int main() {
    int sd, len;
    char buf[64];
    struct sockaddr_un ser;
   
    if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset((char*)&ser, '\0', sizeof(ser));
    ser.sun_family = AF_UNIX;
    strcpy(ser.sun_path, SOCKET_NAME);
    len = sizeof(ser.sun_family) + strlen(ser.sun_path);

    if (connect(sd, (struct sockaddr*)&ser, len) < 0) {
        perror("bind");
        exit(1);
    }

    while(1) {
        memset(buf, '\0', sizeof(buf));
        printf("To Server : ");
        fgets(buf, sizeof(buf), stdin);
        if (send(sd, buf, strlen(buf) + 1, 0) == -1) {
            perror("send");
            exit(1);
        }

        memset(buf, '\0', sizeof(buf));
        if (recv(sd, buf, sizeof(buf), 0) == -1) {
            perror("recv");
            exit(1);
        }
        printf("* From Server : %s\n", buf);
        
        if (!strcmp(buf, "quit")) {
            break;
        }
    }
    close(sd);
 
    return 0;
}

클라이언트 측
서버 측



 

ex3. TCP/IP 프로토콜을 이용해 1:1 대화가 가능하도록 프로그램을 작성하라. 다른 시스템과도 대화가 가능하도록 인터넷 소켓을 사용한다.

fgets(buf, sizeof(buf), stdin);

buf length = strlent(buf) + 1;

 

(ex3_server.c)

#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PORTNUM 9000 

int main() {
    char buf[64];
    struct sockaddr_in sin, cli;
    struct in_addr in;
    int sd, ns, clientlen = sizeof(cli);
   
    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset((char*)&sin, '\0', sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORTNUM);
    sin.sin_addr.s_addr = inet_addr("203.250.148.46");

    if (bind(sd, (struct sockaddr*)&sin, sizeof(sin))) {
        perror("bind");
        exit(1);
    }

    if (listen(sd, 5)) {
        perror("listen");
        exit(1);
    }

    printf("* Wait Client!\n");
    if ((ns = accept(sd, (struct sockaddr*)&cli, &clientlen)) == -1) {
        perror("accept");
        exit(1);
    }
    
    printf("* Client connected!!\n");
    while(1) {
        memset(buf, '\0', sizeof(buf));
        if (recv(ns, buf, sizeof(buf), 0) == -1) {
            perror("send");
            exit(1);
        }
        printf("** From Client : %s\n", buf);

        printf("** To Client : ");
        memset(buf, '\0', sizeof(buf));
        fgets(buf, sizeof(buf), stdin);
        // read(0, buf, sizeof(buf));
        if (send(ns, buf, strlen(buf) + 1, 0) == -1) {
            perror("send");
            exit(1);
        }
        if (!strcmp(buf, "quit\n")) { // 엔터까지 고려
            break;
        }
    }
    close(ns);
    close(sd);
    printf("** End of Communication!!\n");
    
    return 0;
}

 

(ex3_client.c)

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PORTNUM 9000 

int main() {
    int sd;
    char buf[64];
    struct sockaddr_in sin;
   
    memset((char*)&sin, '\0', sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORTNUM);
    sin.sin_addr.s_addr = inet_addr("203.250.148.46");

    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    if (connect(sd, (struct sockaddr*)&sin, sizeof(sin))) {
        perror("bind");
        exit(1);
    }

    while(1) {
        memset(buf, '\0', sizeof(buf));
        printf("To Server : ");
        fgets(buf, sizeof(buf), stdin);
        // read(0, buf, sizeof(buf));
        if (send(sd, buf, strlen(buf) + 1, 0) == -1) {
            perror("recv");
            exit(1);
        }

        memset(buf, '\0', sizeof(buf));
        if (recv(sd, buf, sizeof(buf), 0) == -1) {
            perror("recv");
            exit(1);
        }
        printf("* From Server : %s\n", buf);

        if (!strcmp(buf, "quit\n")) {
            break;
        }
    }
    close(sd);
    printf("* End of Comm to Server\n");

    return 0;
}

클라이언트 사이드
서버 사이드

 

 

 

 

 

 

참고 및 출처: 시스템 프로그래밍 리눅스&유닉스(이종원)