리눅스에서 간단한 파일전송 프로그램 만들기

pchero의 이미지

안녕하세요.

몇일동안 혼자 골머리를 썩히다가 용기를 내어 이곳에 글을 올려 봅니다.

현재 리눅스에서 돌아가는 간단한 파일전송 프로그램을 만들고 있습니다. 대충 윤곽을 잡고 코딩을 했는데 마지막에서 머리를 썩힙니다..;;

현재 문제는 파일전송시 받는부분에서의 open() 함수 문제와 segment fault 입니다.

open()를 fopen()으로 대체하고 여러모로 시도를 해 보았으나 안되더군요..

윈도우 프로그래밍책을 참고로 작성을 하였는데..많이 모르겠습니다.

아니면 제가 참고할 수 있는(초보기준..;;) 간단한 예제 코드라도 알려주세요.

고수님들 부탁드립니다.;;

- receiver.c -

#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 err_quit(char *msg) {
	fputs(msg, stderr);
	fputc('\n', stderr);
	exit(1);
}
 
int recvn(int s, char *buf, int len) {
	int received;
	char *ptr = buf;
	int left = len;
 
	while(left > 0) {
		received = read(s, buf, sizeof(buf));
		if(received == -1)
			return -1;
		else if(received == 0)
			break;
		left -= received;
		ptr += received;
	}
 
	return (len - left);
}
 
 
int main(int argc, char *argv[])
{
	int retval;
 
	int listen_sock = socket(PF_INET, SOCK_STREAM, 0);
	if(listen_sock == -1)
		err_quit("socket() error");
 
	struct sockaddr_in serveraddr;
	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(listen_sock, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
	if(retval == -1)
		err_quit("bind() error");
 
	retval = listen(listen_sock, 5);
	if(retval == -1)
		err_quit("listen() error");
 
	int client_sock;
	struct sockaddr_in clientaddr;
	int addrlen;
	char buf[BUFSIZE];
 
	while(1) {
		addrlen = sizeof(clientaddr);
		client_sock = accept(listen_sock, (struct sockaddr*) &clientaddr, &addrlen);
		if(client_sock == -1)
			err_quit("accept() error");
 
		printf("\n->FileSender connect : IP = %s, Port = %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
 
		char filename[256];
		memset(filename, 0, sizeof(filename));
		retval = recvn(client_sock, filename, 256);
		if(retval == -1) {
			err_quit("recv() error");
			close(client_sock);
			continue;
		}
		printf("-> filename : %s\n", filename);
 
		int totalbytes;
		retval = recvn(client_sock, (char *) &totalbytes, sizeof(totalbytes));
		if(retval == -1) {
			err_quit("recv() error");
			close(client_sock);
			continue;
		}
		printf("-> filesize : %d\n", totalbytes);
 
		FILE *fp = fopen(filename, "wb");
		if(fp == NULL) {
			err_quit("File I/O error");
			close(client_sock);
			continue;
		}
 
		int numtotal = 0;
		while(1) {
			retval = recvn(client_sock, buf, BUFSIZE);
			if(retval == -1) {
				err_quit("recv() error");
				break;
			}
			else if(retval == 0)
				break;
			else {
				fwrite(buf, 1, retval, fp);
				numtotal += retval;
			}
		}
		fclose(fp);
 
		if(numtotal == totalbytes)
			printf("-> File trans complete\n");
		else
			printf("-> File trans failed\n");
 
		close(client_sock);
		printf("FileSender complete : IP = %s, Port = %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
 
	}
 
	close(listen_sock);
 
	return 0;
 
}

- sender.c-

#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 err_quit(char *msg) {
	fputs(msg, stderr);
	fputc('\n', stderr);
	exit(1);
	}
 
int main(int argc, char *argv[])
{
	int retval;
 
	if(argc < 2) {
		fprintf(stderr, "Usage : %s [Filename] \n", argv[0]);
		return -1;
	}
 
	int sock;
	struct sockaddr_in serveraddr;
 
	sock = socket(PF_INET, SOCK_STREAM, 0);
	if(sock == -1)
		err_quit("socket() error");
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(9000);
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /*inet_addr("127.0.0.1");*/
	retval = connect(sock, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
	if(retval == -1)
		err_quit("connect() error");
 
	FILE *fp = fopen(argv[1], "rb");
	if(fp == NULL) 
		err_quit("fopen() error");
 
	char filename[256];
	memset(filename, 0, sizeof(filename));
	sprintf(filename, argv[1]);
	retval = write(sock, filename, sizeof(filename));
	if(retval == -1)
		err_quit("write() error");
 
	fseek(fp, 0, SEEK_END);
	int totalbytes = ftell(fp);
 
	retval = write(sock, (char *)&totalbytes, sizeof(totalbytes));
	if(retval == -1)
		err_quit("write() error");
 
	char buf[BUFSIZE];
	int numread;
	int numtotal = 0;
 
	rewind(fp);
	while(1) {
		numread = fread(buf, 1, BUFSIZE, fp);
		if(numread > 0) {
			retval = write(sock, buf, numread);
			if(retval == -1)
				err_quit("write() error!");
			numtotal += numread;
		}
		else if(numread == 0 && numtotal == totalbytes) {
			printf("file trans complete : %d bytes\n", numtotal);
			break;
		}
		else {
			err_quit("file I/O error");
		}
	}
	fclose(fp);
 
	close(sock);
 
	return 0;
}

이제자자의 이미지

Quote:
int recvn(int s, char *buf, int len) {
	int received;
	char *ptr = buf;
	int left = len;
 
	while(left > 0) {
		received = read(s, buf, sizeof(buf));
		if(received == -1)
			return -1;
		else if(received == 0)
			break;
		left -= received;
		ptr += received;
	}
 
	return (len - left);
}

위에서
received = read(s, buf, sizeof(buf));

received = read(s, ptr, left);

정도로 바꿔보심이..

maximus의 이미지


received = read(s, buf, sizeof(buf)); 이

received = read(s, ptr, left); 로

=================================
:: how about a cup of tea ? ::
=================================

=================================
:: how about a cup of tea ? ::
=================================

pchero의 이미지

계속 디버깅만 하다가 안되서 열만 내고 있었는데...;;

너무 간단한곳에 답이 있었네요..;

감사합니다. 복받으세요!

아직 갈길이 멀군요^^

---------------------------------
제일 왼쪽이 저입니다 :)

익명 사용자의 이미지

위에 꺼에서
#include 뒤에 들어갈 함수 좀 갈켜주세요