본문 바로가기
Ubuntu

[Ubuntu] TCP/IP Socket 통신 클라이언트->서버 파일 전송 C언어로 구현하기

by TYB 2024. 2. 3.
반응형

 

 

서버측 코드

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

void error_handling(char *message);

int main(int argc, char *argv[])
{
  int serv_sock;
  int clnt_sock;
  long int file_size;
  int out;

  struct sockaddr_in serv_addr;
  struct sockaddr_in clnt_addr;
  socklen_t clnt_addr_size;

  char message[]="Hello World!";

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

  serv_sock=socket(PF_INET, SOCK_STREAM, 0);
  if(serv_sock == -1)
        error_handling("socket() error");

  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(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1 )
        error_handling("bind() error");

  if(listen(serv_sock, 5)==-1)
        error_handling("listen() error");

  clnt_addr_size=sizeof(clnt_addr);
  clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr,&clnt_addr_size);
  if(clnt_sock==-1)
        error_handling("accept() error");
long int str_len;
  char *endptr;

// 파일 크기 전송 부분 수정
if ((str_len = read(clnt_sock, message, sizeof(message)-1)) == -1)
    error_handling("read() error!");
message[str_len] = '\0'; // null-terminate the received data
file_size = strtol(message, &endptr, 10); // 10진수로 변환
printf("file_size: %ld\n", file_size);

if((out = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR))<0) {
    perror(argv[2]);
    return -1;
}

// 파일 전송 루프 수정
while (file_size > 0) {
    int read_size = read(clnt_sock, message, sizeof(message));
    printf("rcv data size: %d\n",read_size);
    write(out, message, read_size); // 실제 읽은 크기만큼 전송
    file_size -= read_size; // 파일 크기 감소
} 
  close(out);
  close(clnt_sock);
  close(serv_sock);
  return 0;
}


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

 

클라이언트 측 코드

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

void error_handling(char *message);

int main(int argc, char* argv[])
{
  int sock;
  struct sockaddr_in serv_addr;
  char message[100]="";
  int str_len;
  int n, in;
  long int file_size;
  struct stat file_info;

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

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

  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]));

  if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
        error_handling("connect() error!");

  if((in = open(argv[3],O_RDONLY))<0) {
	  perror(argv[3]);
	  return -1; 
  }
    // 파일 상태 정보 얻기
  if (fstat(in, &file_info) != 0) {
      perror("fstat");
      close(in);
      return -1;
  }
  file_size = file_info.st_size;
  // 파일 크기 출력
  printf("File size: %ld bytes\n", file_size);
  sprintf(message, "%ld" , file_size);
  printf("Send message to Server: %s \n", message);
  write(sock, message, sizeof(message));
  sleep(1);
  // 파일 전송 루프 수정
while (file_size > 0) {
    int read_size = read(in, message, sizeof(message));
    write(sock, message, read_size); // 실제 읽은 크기만큼 전송
    printf("send data size: %d\n",read_size);
    file_size -= read_size; // 파일 크기 감소
}
 // 파일 닫기
  close(in);
  close(sock);
  return 0;
}

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

 

 

 

컴파일 하고

ubuntu@ubuntu8:~/linuxC$ gcc file_client.c -o file_client
ubuntu@ubuntu8:~/linuxC$ gcc file_server.c -o file_server

 

실행하면

 ./file_server 9999 rcv.txt

./ file_client 127.0.0.1 9999 file_server.c

 

정상적으로 파일이 송신 및 수신됩니다.

 

 

 

 

 

 

 

 

 

반응형