티스토리 뷰

728x90

서버와 클라이언트 간의 UDP 통신 프로그램 코드

 클라이언트에서 자기 자신의 소스코드 파일을 읽어들여 서버로 전송하고, 서버에서는 읽어 들인 내용을 파일로 임시 저장합니다. 클라이언트로 부터 특정 문자 "end of file"이라는 메시지를 전송 받으면 메시지 받기 대기를 중단하고, 메시지를 보낼 수 있도록 준비하여 다시 클라이언트로 메시지를 전송합니다. 클라이언트는 recvfrom 으로 전송 받은 메시지를 처음에 전송에 사용했던 파일의 내용과 일치 여부를 확인하는 프로그램 코드입니다.


 서버 응답 대기중 포트번호는 60000번


클리언트는 서버로 접속하기 위해 아래와 같은 명령어를 작성 IP 127.0.0.1, 60000번 포트번호, 읽어 들일 파일명

서버에 전송 받고, 저장된 파일을 다시 읽어 들여 재 전송


UDP를 통해 전송 받은 코드와 처음에 읽어 들인 파일의 내용 일치 확인


서버 소스코드

//--------------------------------------------------------------
// file Name : udp_echoserv.c
// command : cc -o udp_echoserv  udp_echoserv.c
// server 시작 : udp_echoserv  9999
// client에서 전송되는 메시지를 buf.txt 에 저장하고, 다시 client로 전송 후 유효성 체크
//--------------------------------------------------------------
#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
#define BLOCK      255
#define FILENAME "buf.txt"

int main(int argc, char *argv[]) {
    struct sockaddr_in servaddr, cliaddr;
    int s, nbyte, addrlen = sizeof(struct sockaddr);
    char buf[MAXLINE+1];
	FILE *stream; //파일 입출력
    
    //파일명 포트번호
    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);
    }
    
    // 서버 구조
    memset(&cliaddr, 0, addrlen); //bzero((char *)&cliaddr, addrlen);
    memset(&servaddr, 0, addrlen); //bzero((char *)&servaddr,addrlen);
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(atoi(argv[1])); //argv[1]에서 port 번호 가지고 옴

    // 서버 로컬 주소로 bind()
    if(bind(s, (struct sockaddr *)&servaddr, addrlen) < 0) {
        perror("bind fail");
        exit(0);
    }
    
    //저장용 파일 생성
	if((stream = fopen(FILENAME, "w")) == 0) {
        printf("Faile open error\n");
        exit(1);
    }
    while(1)
    {
        puts("Server : waiting request.");
         //전송 받은 메시지 nbyte 저장
        nbyte = recvfrom(s, buf, MAXLINE , 0, (struct sockaddr *)&cliaddr, &addrlen);
        if(nbyte< 0) {
            perror("recvfrom fail");
            exit(1);
        }
        buf[nbyte] = 0; //마지막 값에 0
	
        if(!strncmp(buf, "end of file", 10)) { //마지막 메시지가 end of file이면 종료
            printf("file close");
            fclose(stream); //stream 닫기
            break; //while문 빠져나가기
        } else {
        	printf("%d byte recv: %s\n",nbyte, buf);
            fputs(buf, stream); //파일로 저장
        }
        puts("sendto complete");
    }
	if((stream = fopen(FILENAME, "r")) == NULL) {
		printf("Read File Error");
		exit(1);
	}

	while(!feof(stream)) {
		buf[0] = '\0';
		fgets(buf, BLOCK, stream);
		printf("Send : %s\n", buf);
        //메시지 전송
		if(sendto(s, buf, strlen(buf), 0, (struct sockaddr *)&cliaddr, addrlen) < 0) {
			perror("sendto fail");
			exit(0);
		}
	}
	fclose(stream);
    close(s);
	return 0;
}


클라이언트 소스코드

//--------------------------------------------------------------
// client : udp_echocli.c
// command : cc -o udp_echocli  udp_echocli.c
// localip : udp_echocli  127.0.0.1 8999
// Client 소스코드 파일을 열어서 서버에 전송 및 저장하고, 다시 읽어 들여
// 유효성 체크를 하는 코드
//--------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define MAXLINE  511 //최대값 지정
#define BLOCK 255 //BLOCK 단위로 저장

struct sockaddr_in servaddr;
int addrlen = sizeof(servaddr); //서버 주소의 size를 저장

//메시지 전송 부분 처리
void sendMessage(int s, char* buf) {
    if((sendto(s, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, addrlen)) < 0) {
        perror("sendto fail");
        exit(0);
    }
}

int main(int argc, char *argv[]) {
    int s; //socket
    int nbyte;
    char buf[MAXLINE+1], buf2[MAXLINE+1];
    FILE *stream; //파일 입출력

    //./udp_echocli.c ip주소, 포트번호, 입출력 파일명
    if(argc != 4) {
        printf("usage: %s ip_address port_number filename\n", argv[0]);
        exit(0);
    }

    //socket 연결 0보다 작으면 Error
    if((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket fail");
        exit(0);
    }
    
    //서버 주소 구조
    memset(&servaddr, 0, addrlen); //bzero((char *)&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET; //인터넷 Addr Family
    servaddr.sin_addr.s_addr = inet_addr(argv[1]); //argv[1]에서 주소를 가져옴
    servaddr.sin_port = htons(atoi(argv[2])); //argv[2]에서 port를 가져옴

	if((stream = fopen(argv[3], "r")) == NULL) { //argv[3]의 파일을 open
		printf("Error");
	 	exit(1);
	}

    //stream 파일 읽기 
	while(!feof(stream)) {
		buf[0] = '\0'; //buffer를 초기화
		fgets(buf, BLOCK, stream); //buffer에 BLOCK 만큼 읽어들임

		printf("Send : %s\n", buf); //보낼 메시지 출력
        
   		sendMessage(s, buf);
	}
	fclose(stream);

    sendMessage(s, "end of file"); //파일 입출력 전송 완료 처리

    //recvfrom 처리 부분
	if((stream = fopen(argv[3], "r")) == NULL) {
		printf("Error not File");
		exit(1);
	}
    
	while(!feof(stream))
	{
		buf2[0] = '\0'; //2번째 buffer 초기화
		fgets(buf2, BLOCK, stream); //buf2에 파일을 읽어 들임
		puts("get Server : waiting request.");
        sendMessage(s, buf);
		if((nbyte = recvfrom(s, buf, MAXLINE, 0, 
				(struct sockaddr *)&servaddr, &addrlen)) < 0) {
			perror("recvfrom fail");
			exit(1);
		}
		buf[nbyte] = 0;

		if(strncmp(buf, buf2, BLOCK)) { //전송 받은 buf와 buf2의 값 비교
			printf("Not Match buf : %s\nbuf2 : %s", buf, buf2);
			fclose(stream);
			exit(0);
		} else {
			printf("Match buf : %s\nbuf2 : %s", buf, buf2);
		}
		
		puts("sendto complete");
	}
    
	fclose(stream); //stream close
    close(s); //socket close
    return 0;
}





댓글