ddingz 2022. 1. 3. 17:10

tcp_echocli.c

TCP 클라이언트 프로그램의 예로 에코 서비스를 이용하는 클라이언트 프로그램이다.
표준 인터넷 서비스인 에코는 well-known 포트 7번을 통해 제공되며 클라이언트가 보낸 문자열을 다시 클라이언트로 전송한다.
connect()를 호출한 후 서버와 연결이 완료되면 서버로 전송할 문자열을 키보드를 통해 아래와 같이 입력받는다.

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

fgets() 함수는 스트링 문자열을 입력받는 함수로 첫 번째 인자(buf)는 문자열을 저장할 버퍼이고, 두 번째 인자는 버퍼의 크기, 그리고 세 번째 인자는 입력 스트림 포인터이다.
입력 스트림 포인터로 stdin을 지정하였는데 stdin은 FILE 포인터 타입의 전역변수로 표준 입력 파일인 키보드를 가리킨다.
fgets()로 키보드에서 입력받은 문자열을 write()를 이용해 서버로 전송하고 서버가 에코시켜준 문자열을 read()로 수신하여 화면에 출력한다.

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

#define MAXLINE 127

int main(int argc, char *argv[]) {
    struct sockaddr_in servaddr;
    int s, nbyte;
    char buf[MAXLINE + 1];

    if (argc != 2) {
        printf("usage: %s ip_address\n", argv[0]);
        exit(0);
    }

    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket fail");
        exit(0);
    }

    // 에코 서버의 소켓주소 구조체 작성
    bzero((char *)&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
    servaddr.sin_port = htons(7);

    // 연결요청
    if (connect(s, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("connect fail");
        exit(0);
    }

    printf("입력: ");
    if (fgets(buf, sizeof(buf), stdin) == NULL)
        exit(0);
    nbyte = strlen(buf);

    // 에코 서버로 메시지 송신
    if (write(s, buf, nbyte) < 0) {
        printf("write error\n");
        exit(0);
    }

    // 수신된 에코 데이터 화면 출력
    printf("수신: ");
    if ((nbyte = read(s, buf, MAXLINE)) < 0) {
        perror("read fail");
        exit(0);
    }
    buf[nbyte] = 0;
    printf("%s", buf);

    close(s);

    return 0;
}

실행 결과

./tcp_echocli 127.0.0.1
입력: abcdefg
수신: abcdefg