유닉스(Unix)/네트워크 프로그래밍

토크 클라이언트 프로그램

ddingz 2022. 1. 10. 17:25

이전 글 참고

토크 클라이언트 프로그램에서도 부모 프로세스는 키보드 메시지를 읽어 서버로 전송하며, 자식 프로세스는 상대방이 전송한 메시지를 화면에 출력하는 작업을 각각 수행한다.


tcp_talkcli.c

토크 클라이언트 프로그램이다.
tcp_talkserv.c에서 정의한 input_and_send()와 recv_and_print() 함수를 사용하였다.

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

#define MAXLINE 511

char *EXIT_STRING = "exit"; // 종료문자 정의
int recv_and_print(int sd); // 상대로부터 메시지 수신후 화면 출력
int input_and_send(int sd); // 키보드 입력받고 상대에게 메시지 전달

int main(int argc, char *argv[]) {
    pid_t pid;
    static int s;
    static struct sockaddr_in servaddr;

    // 명령문 입력 인자 처리
    if (argc != 3) {
        printf("사용법: %s server_ip port\n", argv[0]);
        exit(0);
    }

    // 소켓 생성
    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
        printf("Client: Can't open stream socket.\n");
        exit(0);
    }

    // servaddr을 '0'으로 초기화
    bzero((char *)&servaddr, sizeof(servaddr));

    // servaddr 세팅
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
    servaddr.sin_port = htons(atoi(argv[2]));

    // 서버에 연결요청
    if (connect(s, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        printf("Client: can't connect to server.\n");
        exit(0);
    }

    if ((pid = fork()) > 0) // 부모 프로세스
        input_and_send(s);
    else if (pid == 0) // 자식 프로세스
        recv_and_print(s);

    close(s);

    return 0;
}

// 키보드 입력받고 상대에게 메시지 전달
int input_and_send(int sd) {
    char buf[MAXLINE + 1];
    int nbyte;

    while (fgets(buf, sizeof(buf), stdin) != NULL) {
        nbyte = strlen(buf);
        write(sd, buf, strlen(buf));

        // 종료문자열 입력 처리
        if (strstr(buf, EXIT_STRING) != NULL) {
            puts("Good bye.");
            close(sd);
            exit(0);
        }
    }

    return 0;
}

// 상대로부터 메시지 수신후 화면 출력
int recv_and_print(int sd) {
    char buf[MAXLINE + 1];
    int nbyte;

    while (1) {
        if ((nbyte = read(sd, buf, MAXLINE)) < 0) {
            perror("read fail");
            close(sd);
            exit(0);
        }
        buf[nbyte] = 0;

        // 종료문자열 수신 시 종료
        if (strstr(buf, EXIT_STRING) != NULL)
            break;

        printf("%s", buf); // 화면 출력
    }

    return 0;
}

실행 결과