ddingz 2022. 1. 9. 22:18

udp_echoserv.c

UDP 소켓으로 에코 서비스를 하는 프로그램이다.
UDP 에코 서버 프로그램은 클라이언트 프로그램과 거의 같은데 왜냐하면, UDP 통신 프로그램에서는 서버와 클라이언트의 구분이 없고 연결설정 과정도 없기 때문이다.
UDP 프로그램에서 주의할 것은, 한 쪽이 sendto()를 호출했으면 이 데이터를 받기 위해서 상대방은 반드시 recvfrom()을 호출하고 있어야 한다는 것이다.
TCP 소켓에서는 스트림을 이용하므로 write()나 send()로 연속하여 쓰기를 수행하거나 read()나 recv()로 연속하여 읽기를 해도 문제가 되지 않지만, UDP에서는 sendto()와 recvfrom()의 호출이 서로 짝을 이루도록 순서가 맞아야 한다.

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

#define MAXLINE 511

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

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

    // 소켓 생성
    if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket fail");
        exit(0);
    }

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

    // servaddr 세팅
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(atoi(argv[1]));

    // bind() 호출
    if (bind(s, (struct sockaddr *)&servaddr, addrlen) < 0) {
        perror("bind fail");
        exit(0);
    }

    // iterative 에코 서비스 수행
    while (1) {
        puts("Server : waiting request.");

        nbyte = recvfrom(s, buf, MAXLINE, 0, (struct sockaddr *)&cliaddr, &addrlen);
        if (nbyte < 0) {
            perror("recvfrom fail");
            exit(1);
        }
        buf[nbyte] = 0;
        printf("%d byte recv: %s\n", nbyte, buf);

        if (sendto(s, buf, nbyte, 0, (struct sockaddr *)&cliaddr, addrlen) < 0) {
            perror("sendto fail");
            exit(1);
        }
        puts("sendto complete");
    }
}

실행 결과