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

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 뒤에 들어갈 함수 좀 갈켜주세요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.