간단하게짠 ftp프로그램인데요 문제가좀있어서요. 좀 도와주세요

taiha의 이미지

다른건 다 잘되는데요 get 명령으로 16kB 이상의 데이터를 받아오면
파일이 이상해저버려요..

그리고 실행파일의 경우는 파일 크기가 줄어저 생기는데 실행이 아주잘(ㅡ.ㅡ;)
되거든요..

왜근런지 못잡겠어요.. 소켓프로그램은 잘못해서 ㅜ.ㅜ

Redhat 7.3 에서 프로그램 한거에요

사용법은
get a.c b.c
ls
pwd
이런 식이에요

Makefile

all:
	gcc ftpcli.c -o ftpcli
	gcc ftpserv.c -o ftpserv -lcrypt


net.h
#define MYEXIT(str) {perror(str); exit(0);}
#define STR_MAX	512
#define PORT_COMM	56161
#define NUM_CMD	10


#define EOT	"^EOT^"
#define LEN_EOT	5
#define OPK	"^OPK^"	//
#define LEN_OPK	5
#define OPF	"^OPF^"	//명령 수행에 오류생김
#define LEN_OPF	5

unsigned int	size_tran;
/*
//네트웍 바이트오더 고려한 코드
#define MYRECV( fd, buf){ read( fd, &size_tran, sizeof(int) ); size_tran = ntohl(size_tran); read( fd, buf, size_tran ); }
#define MYSEND( fd, buf, size){ size_tran = htonl(size); write( fd, &size_tran, sizeof(int) ); size_tran = ntohl(size_tran); write( fd, buf, size_tran );}
#define SENDSTR( fd, buf ){ size_tran = htonl(strlen(buf)+1); write( fd, &size_tran, sizeof(int) ); size_tran = ntohl(size_tran); write( fd, buf, size_tran );}
*/

//네트웍 바이트오더 고려안한 코드
#define MYRECV( fd, buf){ if( !read( fd, &size_tran, sizeof(int) ) )exit(0);  read( fd, buf, size_tran ); }
#define MYSEND( fd, buf, size){ size_tran = size; write( fd, &size_tran, sizeof(int) ); write( fd, buf, size_tran ); }
#define SENDSTR( fd, buf ){ size_tran = strlen(buf)+1; write( fd, &size_tran, sizeof(int) ); write( fd, buf, size_tran ); }

ftpserv.c
#include <pwd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#define _XOPEN_SOURCE
#include <unistd.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "net.h"

void service( int );
void sig_chld(int);
void myls(int);
void mycd(int);
void mypwd( int );
void myrename( int );
void myput( int );
void myget( int );
void myrm( int );
int login( int );



int	fd_sock_serv,	fd_sock_cli;
int	len_addr_serv, len_addr_cli;
int	num_arg;
struct sockaddr_in	addr_serv, addr_cli, addr_data;
struct passwd	*pwent;
char	arg[2][STR_MAX];

int main()
{
	int	error;

//	if( fork()  != 0 )
//		exit(0);		//안해도 별지장없을거같네쩝.

	chdir( "/" );
	fd_sock_serv = socket(AF_INET, SOCK_STREAM, 0);
	if(fd_sock_serv == -1)
		MYEXIT("socket()")

	addr_serv.sin_family = AF_INET;
	addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
	addr_serv.sin_port = htons(PORT_COMM);
	len_addr_serv = sizeof(addr_serv);
	error = bind( fd_sock_serv, (struct sockaddr *)&addr_serv, len_addr_serv);
	if(error == -1)
		MYEXIT("bind()")


	error = listen(fd_sock_serv, 5);
	if(error == -1)
		MYEXIT("listen()");


	for( ; ; )
	{
		fd_sock_cli = accept( fd_sock_serv,  (struct sockaddr *)&addr_cli, &len_addr_cli );
		if(fd_sock_cli == -1)
			MYEXIT("accept()       ")

		if( fork() == 0 )	//자식 프로세스인 경우 서비스를 시작
		{
			service( fd_sock_cli );
			exit(0);
		}
		else
		{
			signal( SIGCHLD, sig_chld);
			close(fd_sock_cli);
		}
	}
close(fd_sock_serv);
return 0;
}

/*************************	sig_child() 함수	******************************/
void sig_chld(int signo)
{
	wait();
	signal( SIGCHLD, sig_chld);
}
/**************************   login()   ***************************************/
int login( int fd_sock_cli )
{
	FILE 	*fd;
	int	i;
	int	index=0;
	char	id[STR_MAX], passwd[STR_MAX];
	char	tmppw[STR_MAX], tmp[STR_MAX];
	char	shadow[STR_MAX];

	for( i = 0 ; i < 3 ; i++ )
	{
		MYRECV( fd_sock_cli, id );
		MYRECV( fd_sock_cli, passwd );

		pwent = getpwnam( id );
		if( pwent == NULL )
		{
			MYSEND( fd_sock_cli, OPF, LEN_OPF );
			SENDSTR( fd_sock_cli, "사용자가 존재하지않음" );
			continue;
		}

		if( strlen(pwent->pw_passwd)  == 1 )	//shadow 쓰는경우. 아 진짜 힘들다
		{
			fd = fopen("/etc/shadow", "r");
			if( fd == NULL )
				MYEXIT(" /etc/shadow  요거 여는데 에러나네ㅡ.ㅡ;;");
			while(1)
			{
				fgets( tmppw, STR_MAX-1, fd );
				for( i = 0, index = 0;     ; i++, index++)
				{
					if( tmppw[i] ==':' )	//id부분을 다읽음
					{
						index = 0;
						if( strncmp( tmp, pwent->pw_name, strlen(pwent->pw_name) )  == 0)	//id 일치하면
						{
							for(  i++ ;      ;i++, index++)
							{
								if( tmppw[i] == ':' )	//password 다읽음
								{
									tmp[index] = '\0';
									goto getpw;
								}
								tmp[index] = tmppw[i];
							}
						}
						else
							break;
					}
					tmp[index] = tmppw[i];
				}
			}
		}
		getpw:

		if( tmp[0] == '$' )	//MD5 인경우
		{
			if( strcmp( (char *)crypt(passwd, tmp ), tmp) == 0 )	//비번이 일치하면
			{
				MYSEND( fd_sock_cli, OPK, LEN_OPK );
				return 1;
			}
			else
			{
				MYSEND( fd_sock_cli, OPF, LEN_OPF );
				SENDSTR( fd_sock_cli, "비밀번호틀림. 바부팅이!" );
				continue;
			}
		}
		else	//DES인 경우
		{
			char salt[3];
			salt[0] = tmp[0];
			salt[1] = tmp[1];
			salt[2] = '\0';
			if( strcmp( (char *)crypt(passwd, salt), tmp) == 0 )	//비번이 일치하면
			{
				MYSEND( fd_sock_cli, OPK, LEN_OPK );
				return 1;
			}
			else
			{
				MYSEND( fd_sock_cli, OPF, LEN_OPF );
				SENDSTR( fd_sock_cli, "비밀번호틀림. 바부팅이!" );
				continue;
			}
		}
	}
return 0;
}
/****************************   service() 함수  *******************************************/
void service( int fd_sock_cli)
{
	int	cmd;
	int 	i;

	for( i = 0; i < 3; i++)
	{
		if( login( fd_sock_cli) )	//로그인 성공
			goto ok;
	}
	exit(0);


	ok:
	if( setgid( pwent->pw_gid ) == -1)
		exit(0);
	if( setuid( pwent->pw_uid ) == -1)
		exit(0);
	chdir( pwent->pw_dir );

	while(1)
	{
		cmd = -1;
		num_arg = -1;

		MYRECV( fd_sock_cli, &cmd );	//명령 번호르 읽어옴
		MYRECV( fd_sock_cli, &num_arg);	//인자의 수를 읽어옴

		if( num_arg == 1)
		{
			MYRECV( fd_sock_cli, arg[0] );
		}
		else
		{
			if( num_arg == 2 )
			{
				MYRECV( fd_sock_cli, arg[0]);
				MYRECV( fd_sock_cli, arg[1]);
			}
		}

		switch( cmd )
		{
			case 0:		//ls
				myls(fd_sock_cli); break;				
			case 1:		//cd
				mycd(fd_sock_cli); break;
			case 2:		//rename
				myrename(fd_sock_cli); break;
			case 3:		//pwd
				mypwd(fd_sock_cli); break;
			case 4:		//rm
				myrm(fd_sock_cli); break;
			case 5:		//get
				myget(fd_sock_cli); break;
			case 6:		//put
				myput(fd_sock_cli); break;

		}
		for( i =0; i < STR_MAX; i++)
		{
			arg[0][i] = '\0';
			arg[1][i] = '\0';
		}


	}

}

/****************************     myls()            ****************************/
void myls(int fd_sock_cli)
{
	DIR *p_dir;
	struct dirent *dir_ent;
	struct stat stat_buf;
	char	msg[STR_MAX];

	if( (p_dir = opendir(".")) == NULL )
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR( fd_sock_cli, "can't open directory" );
		return;
	}
	else
		MYSEND( fd_sock_cli, OPK, LEN_OPK);

	while( dir_ent = readdir(p_dir) )
	{
		stat(dir_ent->d_name,&stat_buf);
       
		if( S_ISDIR(stat_buf.st_mode) )
		{
			sprintf( msg,"%s/", dir_ent->d_name, strlen(dir_ent->d_name) );
			SENDSTR( fd_sock_cli, msg );
		}
		else
		{
			sprintf( msg,"%s", dir_ent->d_name, strlen( dir_ent->d_name));
			SENDSTR( fd_sock_cli, msg );
		}
	}
	closedir(p_dir);
	MYSEND( fd_sock_cli, EOT, LEN_EOT);
}


/****************************        mycd()         ****************************/
void mycd(int fd_sock_cli)
{
	if( chdir(arg[0]) == -1 )
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR(fd_sock_cli, "directory가 없는디 ㅡ.ㅡ?" );
		return;
	}
	else
		MYSEND( fd_sock_cli, OPK, LEN_OPK);

	MYSEND( fd_sock_cli, EOT, LEN_EOT);
}


/****************************          myget()       ****************************/
void myget( int fd_sock_cli)
{
	int 	fd_get;
	int	readn;
	struct stat	stats;
	mode_t	mode;
	char	buf[STR_MAX];

	fd_get = open( arg[0], O_RDONLY);
	if( fd_get == -1)		//파일이없는경우
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR( fd_sock_cli, "저쪽 파일여는데 실패해부렀네 @.@" );
		return;
	}
	MYSEND( fd_sock_cli, OPK, LEN_OPK);	//파일 열기 성공
	fstat( fd_get, &stats);	
	mode = htonl(stats.st_mode);
	MYSEND( fd_sock_cli, &mode, sizeof( mode_t ) );	//파일모드 전송

	MYRECV( fd_sock_cli, buf );
	if( strncmp( buf, OPF, LEN_OPF) == 0 )
	{
		close(fd_get);
		return;
	}

	while(readn = read( fd_get , buf, STR_MAX))
	{
		MYSEND( fd_sock_cli, buf, readn );
	}

	MYSEND( fd_sock_cli, EOT, LEN_EOT );
	close(fd_get);
}

/****************************       myput()          ****************************/
void myput( int fd_sock_cli)
{
	int 	fd_put;
	mode_t	mode;
	char	buf[STR_MAX];

	MYRECV( fd_sock_cli, buf );	//local 파일 열기 성공여부를 받음
	if( strncmp( buf, OPF, LEN_OPF )  ==  0 )
		return;

	unlink( arg[1]);	//일단 지움
	MYRECV( fd_sock_cli, &mode);	//파일 모드를 받음
	mode = ntohl(mode);
	fd_put = open( arg[1], O_WRONLY|O_CREAT|O_TRUNC, mode);	//파일을 염.
	if( fd_put == -1 )
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR( fd_sock_cli, "저짝 파일 여는데 실패해부러써야.." );
		return;
	}
	MYSEND( fd_sock_cli, OPK, LEN_OPK);
	while(1)
	{
		MYRECV( fd_sock_cli, buf);

		if( strncmp( buf, EOT, LEN_EOT )  ==  0 )
		{
			close( fd_put); 
			return;
		}
		write( fd_put, buf, size_tran );
	}
}


/****************************       myrename()          ****************************/
void myrename(int fd_sock_cli)
{
	if( rename( arg[0], arg[1] ) == -1 )
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR(fd_sock_cli,"파일의 이름을 변경할수 없습니다" );
		return;
	}
	else
	{
		MYSEND( fd_sock_cli, OPK, LEN_OPK);
		SENDSTR(fd_sock_cli,"파일의 이름이 변경 되었습니다." );
	}
	MYSEND( fd_sock_cli, EOT, LEN_EOT);
}


/****************************        mypwd()         ****************************/
void mypwd(int fd_sock_cli)
{
	char dir_name[STR_MAX] = "\0", msg[STR_MAX] = "\0";

	if( getcwd(dir_name,STR_MAX) == NULL )      //현재 디렉토리명을 얻을수 없으면 에러를 출력
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR(fd_sock_cli,"디렉토리가 없는가본디...");
		return;
	}
	else
	{
		MYSEND( fd_sock_cli, OPK, LEN_OPK);
		sprintf( msg, "저쪽 directory는 %s.", dir_name, strlen(dir_name) );
		SENDSTR(fd_sock_cli, msg );
	}
	MYSEND( fd_sock_cli, EOT, LEN_EOT );
}

/****************************   myrm()     ****************************/
void myrm(int fd_sock_cli)
{
	if( unlink( arg[0] ) == -1)
	{
		MYSEND( fd_sock_cli, OPF, LEN_OPF);
		SENDSTR( fd_sock_cli, "파일 제거에 실패하였습니다" );
		return;
	}
	else
	{
		MYSEND( fd_sock_cli, OPK, LEN_OPK);
		SENDSTR( fd_sock_cli, "파일을 제거하였습니다." );
	}
	MYSEND( fd_sock_cli, EOT, LEN_EOT );
}

ftpcli.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include "net.h"

int token( char a[]);
void mylcd();
void mycmd();
void myget( int );
void myput( int );
int login(void);	//반환값은 0,1(실패,성공)


int	num_arg;
int	fd_sock;
char	cmd_list[NUM_CMD][10] = {"ls", "cd",  "rename", "pwd", "rm", "get", "put", "lcd", "quit", "!" };
char	cmd[3][STR_MAX+1];
struct sockaddr_in	addr_serv;
struct hostent		*host_ent_serv;



int main( int argc, char *argv[])
{
	int	i;

	int	error;
	int	len_addr_serv;
	int 	cmd_num;
	char	msg[STR_MAX];
	char 	buf[STR_MAX];


	if( argc != 2 )
	{
		MYEXIT("ftpcli [host]  요거이 표준이제..");
	}
	
	fd_sock = socket( AF_INET,  SOCK_STREAM, 0 );
	if( fd_sock == -1)
		MYEXIT("SOCKET()       ");

	host_ent_serv = gethostbyname( argv[1] );
	if(host_ent_serv == NULL )
		MYEXIT("gethostbyname() error	");

	addr_serv.sin_family = AF_INET;
	addr_serv.sin_addr = *( (struct in_addr *)host_ent_serv->h_addr );
	addr_serv.sin_port = htons(PORT_COMM);
	len_addr_serv = sizeof( addr_serv );

	error = connect( fd_sock, (struct sockaddr *)&addr_serv, len_addr_serv );
	if( error == -1 )
		MYEXIT("connect()         ");

	
	printf(" %s 서버에 연결되었습니다 \n" , argv[1]);


	for( i = 0; i < 3 ; i++)
	{
		if( login() )
			goto login_ok;
	}
	printf("접속 실패\n");
	exit(0);

	login_ok:
	while(1)
	{
		printf("MyFtp>> ");
		fgets( buf, STR_MAX-1, stdin);
		if( buf[0] == '\n' )
			continue;
		buf[strlen(buf)-1] = '\0';	//-1을 한 것은 입력에서의 '\n'을 없애기위함 
		cmd_num = token( buf);

		if( cmd_num  == -1)	//잘못된 명령이면
		{		
			printf( "%s is bad command\n" ,cmd[0]);
			continue;
		}
		MYSEND( fd_sock , &cmd_num, sizeof(int) );
		MYSEND( fd_sock , &num_arg, sizeof(int) );
		if( num_arg == 1)
		{
			SENDSTR( fd_sock, cmd[1]);
		}
		else
		{
			if( num_arg == 2 )
			{
				SENDSTR( fd_sock, cmd[1] );
				SENDSTR( fd_sock, cmd[2] );
			}
		}

		switch( cmd_num )
		{
			case 0:		//ls
			case 1:		//cd
			case 2:		//rename
			case 3:		//pwd
			case 4:		//rm
				MYRECV( fd_sock, msg );
				if(  strncmp( msg, OPF, LEN_OPF )  ==  0 )
				{
					MYRECV( fd_sock, msg );
					printf("%s\n", msg);
					break;
				}
				while(1)
				{
					for( i =0; i < STR_MAX; i++)
						msg[i] = '\0';
					MYRECV( fd_sock, msg );
					if( strlen(msg) == LEN_EOT && strncmp( msg, EOT, LEN_EOT )  ==  0 )
					{
						break;
					}
					printf("%s\n", msg);
				}
				break;
			case 5:		//get
				myget( fd_sock);
				break;
			case 6:		//put
				myput( fd_sock );
				break;
			case 7:
				mylcd();
				break;
			case 8 : 	//quit
				close(fd_sock);
				return 0;
				break;
			case 9 :	// !
				mycmd(); break;
		}
		
	}
close(fd_sock);
return 0;
}

/************************   login()   *************************************/
//반환값은 0(실패), 1(성공)
int login(void)
{
	char	id[STR_MAX], passwd[STR_MAX];
	char	buf[STR_MAX];

	printf("ID : ");
	fgets( id, STR_MAX-1, stdin);
	id[strlen(id)-1] = '\0';	//-1을 한 것은 입력에서의 '\n'을 없애기위함 

	printf("PASSWORD : ");
	fgets( passwd, STR_MAX-1, stdin);
	passwd[strlen(passwd)-1] = '\0';	//-1을 한 것은 입력에서의 '\n'을 없애기위함 

	SENDSTR( fd_sock, id );
	SENDSTR( fd_sock, passwd );
	
	MYRECV( fd_sock, buf );
	if( strncmp( buf, OPF, 5 ) == 0 )
	{
		MYRECV( fd_sock, buf );
		printf("%s\n", buf);
		return 0;
	}
return 1;
}


/********************************	token()	**********************************/
//올바른 명령이면 해당 명령의 번호, 잘못된 명령이면 -1을 반환
int token( char buf[] )
{
	int	i, index= 0, flag;

	for( i =0; i < STR_MAX; i++)
	{
		cmd[0][i] = '\0';
		cmd[1][i] = '\0';
		cmd[2][i] = '\0';
	}

	num_arg = 0;
	flag = 0;	//공백이면 0, 아니면 1
	for( i = 0; buf[i] != '\0'; i++)
	{
		if( num_arg > 2)
			return -1;

		if( buf[i] != ' ' && buf[i] != '\0' )	//공백또는 스트링의 끝이 아니면 
		{
			cmd[num_arg][index] = buf[i];
			index++;
			flag = 1;
			continue;
		}
		if( flag != 0 )	//이전 문자가 공백이 아니면 카운트를 증가
		{
			flag = 0;
			cmd[num_arg][index] = '\0';
			num_arg++;
			index = 0;
		}
	}
	for( i = 0; i < NUM_CMD; i++)	//입력받은 명령어의 번호 return
	{
		if( strcmp( cmd_list[i], cmd[0] )  == 0 )
			return i;
	}

return -1;
}

/****************************     mylcd()            ****************************/
void mylcd()
{
	if( chdir( cmd[1] ) == -1 )
	{
		printf("디렉토리 변경이 실패 하였습니다\n");
	}
}

/****************************     mycmd()            ****************************/
void mycmd()
{
	system( cmd[1] );
}

/****************************** myget()   *************************/
void myget(int fd_sock)
{
	mode_t	mode;
	int 	fd_get;
	char	buf_get[STR_MAX];

	MYRECV( fd_sock, buf_get );	//받을 파일을 열었는지 확인
	if( strncmp( buf_get, OPF, LEN_OPF) == 0 )	//받을 파일 열기 실패
	{
		MYRECV( fd_sock, buf_get );
		printf("%s\n", buf_get);
		return;
	}
	unlink( cmd[2] );	//안묻고걍지움
	MYRECV( fd_sock, &mode);	//파일 모드를 받음
	mode = ntohl(mode);
	fd_get = open( cmd[2], O_WRONLY|O_CREAT|O_TRUNC, mode);	//파일 염
	if( fd_get == -1 )
	{
		printf("Can't open local file\n");
		close(fd_get);
		MYSEND(fd_sock, OPF, LEN_OPF);
		return;
	}
	MYSEND(fd_sock, OPK, LEN_OPK);
	while(1)
	{
		MYRECV( fd_sock, buf_get );
		if( strncmp( buf_get, EOT, LEN_EOT )  ==  0 )
		{
			close( fd_get); 
			return;
		}
		write( fd_get, buf_get, size_tran );
	}
	close(fd_get);
}
/********************************* myput()   **************************/
void myput( int fd_sock )
{
	int 	fd_put;
	int	readn;
	struct stat	stats;
	mode_t	mode;
	char	buf_put[STR_MAX];

	fd_put = open( cmd[1], O_RDONLY);
	if( fd_put == -1)
	{
		MYSEND(fd_sock, OPF, LEN_OPF );
		printf("Can't open file\n");
		return;
	}
	MYSEND(fd_sock, OPK, LEN_OPK );	//local 파일 열기 성공

	fstat( fd_put, &stats);	
	mode = htonl(stats.st_mode);
	MYSEND( fd_sock, &mode, sizeof( mode_t ) );	//파일모드 전송


	MYRECV( fd_sock, buf_put );
	if( strncmp( buf_put, OPF, 5) == 0)	//서버측 파일열기 실패
	{
		MYRECV( fd_sock, buf_put );
		printf("%s\n", buf_put);
		return;
	}
	while( readn = read( fd_put , buf_put, STR_MAX))
	{
		MYSEND( fd_sock, buf_put, readn );
	}
	MYSEND( fd_sock, EOT, LEN_EOT);
	close(fd_put);
}
pynoos의 이미지

unsigned int   size_tran; 

#define MYRECV( fd, buf){ read( fd, &size_tran, sizeof(int) ); size_tran = ntohl(size_tran); read( fd, buf, size_tran ); } 

#define MYSEND( fd, buf, size){ size_tran = htonl(size); write( fd, &size_tran, sizeof(int) ); size_tran = ntohl(size_tran); write( fd, buf, size_tran );} 

두번송신에 두번 수신하는 모습으로 되어있는데, 사실 이렇게 되려면,
처음 송신한 길이부분이 확실히 전송되었는지, 확실히 수신되었는지를
확인시켜줘야합니다.

즉, 두번째에 있는 read,write를 보면,
송신하는 녀석의 return 값이 원하는 만큼 송신되지 않을 수 도 있고,
수신하는 녀석의 return 값이 기대하는 만큼 오지 않을 수 도 있습니다.
두 경우에 대해서 원하는 만큼이 될 때까지 loop을 돌아야하구요...
loop을 돌다가 connection이 끊어지는 것도 처리해줘야하지요....

macro보다는 함수로 만드는 것이 좋겠네요.

제가 자주하는 말인데, TCP/IP에서처럼 연결지향 전송에서는 송신한 수와 수신한 수는 일치하지 않을 수 있고, 송신한 양과 수신한 양이 일치하는 것을 전제로 합니다.

taiha의 이미지

전송량을 확인하기위해 매크로뒷부분에

MYRECV {..... printf("%d\n",size_tran}; }

이런식으로해서 전송된 크기를 보면 서버측의 전송크기는 정확한데

클라이언트즉의 전송크기가 16kB 전송 이후로 이상한값이 들어가버립니다.

put 의 경우에는 위의 문제가 없고요. 다른경우도 마찬가지 입니다

님의 말씀대로 해보긴 하겠습니다. 근데 get 에서만 문제가 생기는 이유는 정말 모르겠네요

김경태의 이미지

그렇게 하시고,
if ( n != readn ( sd, buff, n ))
{
에러처리;
}

이런식으로 사용하세요. 물론 이것도 문제는 있을 수 있지만....

큰 문제는 없을 겁니다.

댓글 달기

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