[socket programming] udp를 이용한 파일 전송 프로그램

2020. 12. 11. 16:47CS/네트워크

server 코드 (UDPserver.c)

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

#define BUFSIZE 1024

void error_handling(char *message);

int main(int argc, char **argv){
    FILE* file;
    int sd;
    char file_name[BUFSIZE];

    char buf[BUFSIZE];
    int buf_len;
    int filename_len;

    struct sockaddr_in serv_addr;
    struct sockaddr_in clnt_addr;
    int clnt_addr_size = sizeof(clnt_addr);

    if(argc!=2){
        printf("UDP server  %s <port_num>\n", argv[0]);
        exit(1);
    }

    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if(sd == -1)
        error_handling("socket() error!");

    struct timeval optVal = {5,0};
    int optLen = sizeof(optVal);
    if(setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,&optVal, optLen) == -1){
        error_handling("setsockopt error\n");
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_addr.sin_port=htons(atoi(argv[1]));

    if(bind(sd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
        error_handling("bind() error");

    int i;
    for(i=0; i < 30; i++){
        filename_len = recvfrom(sd,file_name,BUFSIZE,0,(struct sockaddr*)&clnt_addr, &clnt_addr_size);
        file = fopen(file_name,"wb");
        clnt_addr_size = sizeof(clnt_addr);
        sleep(1);
     }
    while(buf_len = recvfrom(sd,buf,BUFSIZE,0,(struct sockaddr*)&clnt_addr,&clnt_addr_size)>0){
        fwrite(buf,sizeof(char), buf_len,file);
        sendto(sd,buf,buf_len,0,(struct sockaddr*)&clnt_addr,sizeof(clnt_addr)); 

        if(buf_len == 0)
           break;
    }

    fclose(file);
    close(sd);
    return 0;
}

void error_handling(char *message)
 {
      fputs(message, stderr);
      fputc('\n', stderr);
      exit(1);
 }

client 코드 (UDPclient.c)

#include <stdio.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>
#include <sys/time.h>

#define BUFSIZE 1024
void error_handling(char *message);

int main(int argc, char **argv){
   int sock;
   int addr_size;

   struct sockaddr_in serv_addr;
   struct sockaddr_in from_addr;

   if(argc!=4){
      printf("Usage %s <IP> <port> <file name>\n", argv[0]);
      exit(1);
   }

   sock = socket(PF_INET, SOCK_DGRAM,0);
   if(sock == -1)
      error_handling("UDP socket error");

   struct timeval optVal = {5, 0};
   int optLen = sizeof(optVal);
   if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &optVal, optLen) == -1){
      error_handling("setsockopt error\n");
   }

   memset(&serv_addr,0,sizeof(serv_addr));
   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
   serv_addr.sin_port = htons(atoi(argv[2]));
   addr_size = sizeof(from_addr);

   int total_bufnum;
   long filesize;
   char buf[BUFSIZE];
   int sendlength;
   int sendbuf = 0;
   int success;


   FILE* file; //파일
   if((file = fopen(argv[3], "rb")) == NULL) { //argv[3]의 파일을 open
      printf("Error");
       exit(1);
   }
   if(file == NULL){
      printf("File is not exit");
      exit(1);
   }

   fseek(file, 0, SEEK_END); //파일의 맨 마지막으로 이동
   filesize = ftell(file); //파일 위치 값을 리턴 (현재 파일 마지막 위치를 리턴)
   fseek(file, 0, SEEK_SET); //파일 제일 처음으로 이동

   int i = 0;
   for(i = 0; i < 30; i++){
      sendto(sock,argv[3] ,strlen(argv[3]),0,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
      sleep(5);
   }

   while((sendlength = fread(buf, sizeof(char), sizeof(buf), file) > 0)) {
      sendto(sock,buf ,sendlength,0,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
   }


   printf("send file done\n");

   close(sock);
   return 0;
}

void error_handling(char* message)
{
   fputs(message,stderr);
   fputc('\n',stderr);
   exit(1);
}

server 쪽은  ./UDPserver <port num>

client 쪽은  ./UDPclient <ip addr> <port num> <file name>

으로 실행하면 파일 이름과 파일 내용 일부는 전송이 되지만 전체가 제대로 전송은 되지 않는것을 알 수 있다.