리눅스 소켓프로그래밍 간단한 파일전송 프로그램

love1163의 이미지

안녕하세요..^^
제가 이번에 리눅스에서의 소켓프로그래밍을 배우는데요.
간단한 메신져를 만들었습니다.
그래서 이번엔 간단한 파일전송 프로그램을 만들려고 하는데요.
우선 여기서 있는 몇개의 예제를 참고하여..
제 메신져 프로그램에 적용해 보았습니다.
근데 에러 없이 돌아가기는 하는데..
클라이언트에서 서버로 파일이 전송은 되질않네요..

제가 초보자라서 어느부분이 문제인지도 찾질 못하겠습니다..
문제점과 해결책좀 제시해 주셨으면 좋겠습니다..^^
제가 초보인지라 상세하게 설명해주시면 감사하겠습니다..

클라이언트에서 서버로 파일을 보내는 방식입니다..

server source

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
 
#define MAXSIZE 2048
 
// AF_INET Server
main()
{
	int server_sockfd, client_sockfd;
	int server_len, client_len;
	struct sockaddr_in server_address;
	struct sockaddr_in client_address;
	char ip[128];
	char port[128];
	int filedes, filelen;
	long total;
 
	printf("MyServer#> IP_Address Input : ");
	fgets(ip, 127, stdin);
	ip[strlen(ip)-1] = 0;
	printf("MyServer#> Port Number Input :");
	fgets(port, 127, stdin);
	port[strlen(port)-1] = 0;
 
	/* Create an unnamed socket for the server. */
	server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = inet_addr(ip);
	server_address.sin_port = htons(atoi(port));
	server_len = sizeof(server_address);
	bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
 
	listen(server_sockfd, 5);
	client_len = sizeof(client_address);
	client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
 
	char filename[256];	
	char buf[MAXSIZE];
	read(client_sockfd, filename, strlen(filename));
	filedes = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 
	read(client_sockfd, buf, MAXSIZE);
	total = atoi(buf);
	printf("receive file size %ld\n", total);
 
	while((filelen=read(client_sockfd ,buf, MAXSIZE)) > 0)
	{
		filelen = write(filedes, buf, filelen);
 
		if(filelen == MAXSIZE)
		{
			total -= (long)filelen;
			continue;
			printf("receive success %ldpercent\n", total);
		}
		else if(filelen < MAXSIZE)
		{
			total -= (long)filelen;
			if(total <= 0)
			{
				printf("receive success\n");
				break;
			}
			printf("not success receive %ld percent\n", total);
		}
		else if(filelen == -1)
		{
			printf("receive failed\n");
			exit(0);
		}
	}
 
	close(client_sockfd);
	close(filedes);
}

client source

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
 
#define MAXSIZE 2048
 
// AF_INET - Client
main()
{
	int sockfd;
	int len;
	struct sockaddr_in address;
	int result;
	char ip[128];
	char port[128];
    char filename[256];
    char buf[MAXSIZE];
	int filedes, filelen;
	long total;
 
	printf("MyClient#> IP Address Input : ");
	fgets(ip, 127, stdin);
	ip[strlen(ip)-1] = 0;
	printf("MyClient#> Port Number Input : ");
	fgets(port, 127, stdin);
	port[strlen(port)-1] = 0;
 
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr(ip);
	address.sin_port = htons(atoi(port));
	len = sizeof(address);
 
	result = connect(sockfd, (struct sockaddr *)&address, len);
 
	if(result == -1) {
		perror("oops: MyClient");
	}
 
	printf("MyClient#> Filename -> ");
	fgets(filename, 255, stdin);
	filename[strlen(filename)-1] = 0;
	write(sockfd, filename, strlen(filename));
 
	filedes = open(filename, O_RDONLY, 0);
	total = lseek(filedes, 0, SEEK_END);
 
	printf("send filesize %ld \n", total);
    sprintf(buf, "%ld", total);
	write(sockfd, buf, MAXSIZE);
 
	lseek(filedes, 0, SEEK_SET);
	while((filelen = read(filedes, buf, MAXSIZE)) > 0)
	{
		filelen = write(sockfd, buf, filelen);
 
		if(filelen == MAXSIZE)
		{
			total -= (long)filelen;
			if(total <= 0)
			{
				printf("file send success\n");
				filelen = 0;
				break;
			}
			else
			{
				printf("success file send %ldpercent  \n", total);
				continue;
			}
		}
		else if(filelen < MAXSIZE)
		{
			total -= (long)filelen;
			if(total <= 0)
			{
				printf("success\n");
				break;
			}
			printf("not success %d sending %ld percent \n", filelen, total);
		}
		else if(filelen == -1)
		{
			printf("file send failed\n");
			exit(0);
		}
	}
 
	close(sockfd);
	close(filedes);
}

모가 문제인지 도무지 모르겠습니다..
아참..
include는 안올라가서 그부분만 수정하겠습니다.
sys/types.h
sys/socket.h
stdio.h
netinet/in.h
arpa/inet.h
unistd.h
fcntl.h
이게 헤더파일들 입니다..^^

kaje0105의 이미지

서버에서 클라이언트로 전송하는건 잘 되나요?

만약 그렇다면 소스상에서 문제를 찾지 마시고 네트워크 쪽을 검토해보세요

익명 사용자의 이미지

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

socket() 함수의 첫번째 인자는 protocol family가 들어가야 하는거 아닌가요 ?
address family가 들어가도 실행이 되는지 궁금하네요 ..

익명 사용자의 이미지

AME
socket - create an endpoint for communication

SYNOPSIS
#include /* See NOTES */
#include

int socket(int domain, int type, int protocol);

DESCRIPTION
socket() creates an endpoint for communication and returns a descriptor.

The domain argument specifies a communication domain; this selects the protocol family which will be used for communication. These families are defined in
. The currently understood formats include:

Name Purpose Man page
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols ipv6(7)
AF_IPX IPX - Novell protocols
AF_NETLINK Kernel user interface device netlink(7)
AF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
AF_AX25 Amateur radio AX.25 protocol
AF_ATMPVC Access to raw ATM PVCs
AF_APPLETALK Appletalk ddp(7)
AF_PACKET Low level packet interface packet(7)

The socket has the indicated type, which specifies the communication semantics. Currently defined types are:

SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band data transmission mechanism may be supported.

SOCK_DGRAM Supports datagrams (connectionless, unreliable messages of a fixed maximum length).

SOCK_SEQPACKET Provides a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length; a consumer is required to read an
entire packet with each input system call.

SOCK_RAW Provides raw network protocol access.

SOCK_RDM Provides a reliable datagram layer that does not guarantee ordering.

SOCK_PACKET Obsolete and should not be used in new programs; see packet(7).

Some socket types may not be implemented by all protocol families; for example, SOCK_SEQPACKET is not implemented for AF_INET.

sunyzero의 이미지

TCP 전송은 스트림 경계가 보존되지 않습니다.
송신측이 send, send로 2번 전송했을때 수신측이 recv, recv 2번으로 받는게 아니라는 것이죠.

그렇기 때문에 송신측과 수신측이 통신할 때,
길이를 알수 있는 헤더 정보나 구분자(delimiter)를 정해야 합니다.

send로 파일명을 보내는 부분이나 크기를 보내는 부분을 정확하게 read측에서 딱 그만큼을 읽지는 못합니다.
더군다나 read할 때 strlen은 왜 하는 것인지요? 이 부분은 잘못된 사용입니다.

TCP의 개념을 다시 잡으시고 전체적으로 다시 작성하시는게 좋을 듯 합니다.

========================================
* The truth will set you free.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.