/* ************************************************** */
/*    Image Receiver Program  (ARM version)           */
/*    This Program is to receive the jpeg image file  */
/*    and show the jpeg image file                    */
/*                                                    */
/*                   2006.7.7  Made By Jung Yong Hak  */
/* ************************************************** */
// header file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define BUFSIZE 4096
void error_handling(char *message);
// 사용자 정의 데이터 수신 함수
int recvn(int s, char *buf, int len, int flags)
{
 int received;  //리턴 상태 표시 변수
 char *ptr = buf; //받은 데이터를 저장할 버퍼에 대한 포인터
 int left = len;  //남은 크기(바이트 수) 저장할 변수
 while(left > 0){
  // 네트워크로 받은 바이트의 수를 리턴
  received = recv(s, ptr, left, flags);
  // 받기 실패시 -1 리턴
  if(received == -1)
   return -1;
  else if(received == 0)
   break;
  left -= received; // 받은 바이트 수 만큼 빼서 남은 크기를 알려줌
  ptr += received; // 포인터은 받은 바이트 수 만큼 더해준다
 }
 return (len - left); // 전체 길이에서 남은 바이트 수를 빼서 리턴
}
int main(int argc, char* argv[])
{
 //argument
 int serv_sock,client_sock;
 int retval,i,addrlen,numtotal=0;
 int kill_pid, check_pid=1, totalbytes=0;
 char buf[BUFSIZE];
 char system_arg[256];
 char filename[256],file_tmp[256]="2006";
 struct sockaddr_in serveraddr,clientaddr;
 FILE *fp;
 pid_t pid;
 char *exec_arg[4];
 puts("Image Receiver Program");
 puts("=========================================");
 // socket()
 serv_sock = socket(AF_INET, SOCK_STREAM, 0);
 if(serv_sock == -1) error_handling("socket()");
 
 // bind()
 memset(&serveraddr,0,sizeof(serveraddr));
 serveraddr.sin_family = AF_INET;
 serveraddr.sin_port = htons(9000);
 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 retval = bind(serv_sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
 if(retval == -1) error_handling("bind()");
 
 // listen()
 retval = listen(serv_sock, 5);
 if(retval == -1) error_handling("listen()");
 while(1)
 {
  // accept()
  addrlen = sizeof(clientaddr);
  client_sock = accept(serv_sock, (struct sockaddr *)&clientaddr, &addrlen);
  if(client_sock == -1)
  {
   error_handling("accept()");
   continue;
  }   
  // 접속 ip 와 port를 출력
  printf("IP =%s, port =%dn",
   inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
 
  memset(&filename,0, 256);
  // 받은 원래 파일 이름 출력 (후에 파일이름 변경한다)
  retval = recvn(client_sock, filename, 256, 0);
  if(retval == -1)
  {
   error_handling("recv()");
   close(client_sock);
   continue;
  }
  printf("-> original file name : %sn", filename);
 
  retval = recvn(client_sock, (char *)&totalbytes, sizeof(totalbytes), 0);
  // 파일 크기 출력
  if(retval == -1 )
  {
   error_handling("recv()");
   close(client_sock);
   continue;
  }
  printf("-> file size : %dn", totalbytes);
  // 파일 이름 변경 후 출력
  for(i=26;i<45;i++)
  {
   file_tmp[i-22]=filename[i];
  }
  strcpy(filename,file_tmp);
  printf("-> changed file name : %sn",filename);
  // 파일 열기
  fp= fopen(filename, "wb");
  if(fp == NULL)
  {
   perror("파일 입출력 오류");
   close(client_sock);
   continue;
  }
  while(1)
  {
   retval = recvn(client_sock, buf, BUFSIZE, 0);
   //retval이 -1이면 에러
   if(retval == -1)
   {
    error_handling("recv()");
    break;
   }
   //retval이 0이면 전체파일 다 보냈다는 것
   else if(retval == 0)
    break;
   else
   {
    /* 1바이트 크기의 데이터를 retval개수 만큼 fp로 출력
     buf는 출력하고자 하는 데이터의 시작위치를 가리키는 포인터 */
    fwrite(buf, 1, retval, fp);
    if(ferror(fp))
    {
     perror("파일 입출력 오류");
     break;
    }
    numtotal += retval; //받은 만큼 + 시켜준다
   }
  }
  fclose(fp);
  // 전송 결과 출력
  if(numtotal == totalbytes)
  {
   printf("-> file transfer success!n");
   numtotal=0;
  }
  else
  {
   printf("-> file transfer fail!n");
   numtotal=0;
  }
  // 파일 전송후 close client_socket
  close(client_sock);
  // argument 입력
  exec_arg[0]="showimg";
  exec_arg[1]="-qws";
  exec_arg[2]=filename;
  exec_arg[3]=0; // 0 == NULL
  // check_pid 가 0일 경우
  if(check_pid==0)
  {
   // system_arg변수에 kill PID를 입력후 실행 해서 프로세스를 죽임
   sprintf(system_arg, "kill %d",kill_pid);
   system(system_arg);
   // 프로세스 체크 변수에 1 대입
   check_pid=1;
  }
  switch(pid=fork())
  {
  case -1:
   printf("errorn");
   break;
  case 0:
   // print the current PID and parent PID & save current PID
   printf("parent PID : %d, current PID : %dn", getppid(), getpid());
   kill_pid=getpid();
   // execv
   execv("/jffs/Qtopia/bin/showimg",exec_arg);
   // 프로세스가 살아 있다는 걸 알리기 위한 변수에 0 입력
   check_pid=0;
   break;
  default:
   break;
  }
 }
 // closesocket()
 close(serv_sock);
 return 0;
}
// 소켓 함수 오류 출력 후 종료
void error_handling(char *message)
{
 fputs(message, stderr);
 fputc('n',stderr);
 exit(1);
}
Posted by 용학도리
,