ftpclient ftp客户端源码

ftp客户端自己搭建,已经测试在linux和windos下面的ftpsvr可以连接成功和传输图像,

出现windos上次图片失败的问题, windos下文件名称不能包含 

“?”、“、”、“╲”、“/”、“*”、““”、“”“、“<”、“>”、“|”。:

(需要源码和测试信息联系QQ:123011785)

经过修改测试相对稳定,下面附加代码信息

ftp.h源码:

#ifndef __VSS_FTP_CLIENT_H__
#define __VSS_FTP_CLIENT_H__
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <errno.h>
#include <assert.h>
#include <netinet/in.h>
#include <dirent.h>
#include <ctype.h>

using namespace std;

#define bb_perror_msg(x) printf(x)
#define bb_msg_read_error "Error: bb_msg_read_error"
#define bb_msg_write_error "Error: bb_msg_write_error"
#define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
#define bb_perror_msg_and_die printf
#define bb_error_msg_and_die printf
#define bb_perror_nomsg_and_die() assert(0);

//#define TRACE() printf("%s %d\n", __FUNCTION__, __LINE__);
#define OFF_FMT "l"

typedef struct len_and_sockaddr {
	socklen_t len;
	union {
		struct sockaddr sa;
		struct sockaddr_in sin;
	};
} len_and_sockaddr;

typedef struct ftp_host_info_s {
	const char *user;
	const char *password;
	struct len_and_sockaddr *lsa;
} ftp_host_info_t;

#ifdef  __cplusplus
extern "C" 
{
#endif
	int xatou(char *buf);
	int xatoul_range(char *buf, int low, int top);
	len_and_sockaddr *xhost2sockaddr(const char *ip_addr, int port);
	char* sockaddr2str(const struct sockaddr *sa, int flags);
	char* xmalloc_sockaddr2dotted(const struct sockaddr *sa);
	int xopen3(const char *pathname, int flags, int mode);
	int xopen(const char *pathname, int flags);
	void safe_fclose(FILE *control_stream);
	ssize_t safe_read(int fd, void *buf, size_t count);
	ssize_t safe_write(int fd, const void *buf, size_t count);
	size_t full_write(int fd, const void *buf, size_t len);
	off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size);
	off_t bb_copyfd_eof(int fd1, int fd2);
	void ftp_die(const char *msg, const char *remote);
	int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf);
	void set_nport(len_and_sockaddr *lsa, unsigned port);
	int xconnect_ftpdata(ftp_host_info_t *server, char *buf);
	void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen);
	int xsocket(int domain, int type, int protocol);
	int xclose(int s);
	int xconnect_stream(const len_and_sockaddr *lsa);
	FILE *ftp_login(ftp_host_info_t *server);
	int ftp_mkdir(FILE *control_stream, const char *FoldName);
	int ftp_cd(FILE *control_stream, const char *FoldName);
	int ftp_send(ftp_host_info_t *server, FILE *control_stream,
			const char *server_path, char *local_path);
	int ftp_quit(FILE *control_stream);
	//int main(void);
#ifdef __cplusplus
}
#endif

#endif


ftp.c源码如下:

#include "ftpclient.h"

#if 0
enum {
	LSA_SIZEOF_SA = sizeof(
		union {
			struct sockaddr sa;
			struct sockaddr_in sin;
		}
	)
};
#endif
typedef struct	ftpmissions{
	int currmission_id;
	int len_missionlist;
}ftpmissions_t;
typedef struct	ftpbackupmission_info{
	int currfilelist_id;
	int len_filelist;
}ftpbackupmission_info_t;

int xatou(char *buf)
{
	char c;
	int i;
	int j = 0;
	int retval = 0;
	char mod[3] = {1, 10, 100};
	int len = strlen(buf);
	if ( (!len)||(len > 3) )
	{
		return -1;
	}	

	for (i = len - 1; i >= 0; i--)
	{
		c = buf[i];
		retval += atoi(&c)*mod[j++];
	}
	return retval;
}
int xatoul_range(char *buf, int low, int top)
{
	int retval = xatou(buf);
	if (retval < low)
	{
		retval = low;
	}	

	if (retval > top)
	{
		retval = top;
	}
//	printf("buf = %s\n", buf);	
//	printf("###retval = %d\n", retval);
	return retval;
}
len_and_sockaddr *xhost2sockaddr(const char *ip_addr, int port)
{
	int rc;
	len_and_sockaddr *r = NULL;
	struct addrinfo *result = NULL;
	struct addrinfo hint;
	memset(&hint, 0, sizeof(hint));
	hint.ai_family = AF_INET;
	hint.ai_socktype = SOCK_STREAM;
	rc = getaddrinfo(ip_addr, NULL, &hint, &result);
	if (rc||!result)
	{
		free(r);		
		r = NULL;
		return r;
	}
	r = (len_and_sockaddr *)malloc(4 + result->ai_addrlen);
	if (r == NULL)
	{
		return NULL;
	}
	r->len = result->ai_addrlen;
	memcpy(&r->sa, result->ai_addr, result->ai_addrlen);
	r->sin.sin_port = htons(port);
	freeaddrinfo(result);	
	return r;	
}
/******************************************************************/
#define IGNORE_PORT NI_NUMERICSERV
char* sockaddr2str(const struct sockaddr *sa, int flags)
{
	char host[128];
	char serv[16];
	int rc;
	socklen_t salen;

	//salen = LSA_SIZEOF_SA;
	salen = sizeof(sockaddr);
	rc = getnameinfo(sa, salen,
			host, sizeof(host),
			/* can do ((flags & IGNORE_PORT) ? NULL : serv) but why bother? */
			serv, sizeof(serv),
			/* do not resolve port# into service _name_ */
			flags | NI_NUMERICSERV
			);
	if (rc)
		return NULL;
	if (flags & IGNORE_PORT)
		return strdup(host);
	/* For now we don't support anything else, so it has to be INET */
	/*if (sa->sa_family == AF_INET)*/
	char *retmsg = (char *)malloc(2048);
	memset(retmsg, 0, 2048);
	sprintf(retmsg, "%s:%s", host, serv);
	return retmsg;
	/*return xstrdup(host);*/
}

char* xmalloc_sockaddr2dotted(const struct sockaddr *sa)
{
	return sockaddr2str(sa, NI_NUMERICHOST);
}

int xopen3(const char *pathname, int flags, int mode)
{
	int ret;

	ret = open(pathname, flags, mode);
	if (ret < 0) {
		bb_perror_msg_and_die("can't open '%s'", pathname);
	}
	return ret;
}
int xopen(const char *pathname, int flags)
{
	return xopen3(pathname, flags, 0666);
}

void safe_fclose(FILE *control_stream)
{
	if (control_stream != NULL)
	{
		printf("+++++++++close ftp control_stream!!!!\n\n");
		fclose(control_stream);
		control_stream = NULL;
	}
}

ssize_t safe_read(int fd, void *buf, size_t count)
{
	ssize_t n;

	do {
		n = read(fd, buf, count);
	} while (n < 0 && errno == EINTR);

	return n;
}
ssize_t safe_write(int fd, const void *buf, size_t count)
{
	ssize_t n;

	do {
		n = write(fd, buf, count);
	} while (n < 0 && errno == EINTR);

	return n;
}
size_t full_write(int fd, const void *buf, size_t len)
{
	ssize_t cc;
	ssize_t total;

	total = 0;

	while (len) {
		cc = safe_write(fd, buf, len);

		if (cc < 0)
			return cc;	/* write() returns -1 on failure. */

		total += cc;
		buf = ((const char *)buf) + cc;
		len -= cc;
	}

	return total;
}



off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
{
	int status = -1;
	off_t total = 0;
	char buffer[BUFSIZ];
	if (src_fd < 0)
		goto out;

	if (!size) {
		size = BUFSIZ;
		status = 1; /* copy until eof */
	}

	while (1) {
		ssize_t rd;
		rd = safe_read(src_fd, buffer, size > BUFSIZ ? BUFSIZ : size);

		if (!rd) { /* eof - all done */
			status = 0;
			break;
		}
		if (rd < 0) {
			bb_perror_msg(bb_msg_read_error);
			break;
		}
		/* dst_fd == -1 is a fake, else... */
		if (dst_fd >= 0) {
			ssize_t wr = full_write(dst_fd, buffer, rd);
			if (wr < rd) {
				bb_perror_msg(bb_msg_write_error);
				break;
			}
		}
		total += rd;
		if (status < 0) { /* if we aren't copying till EOF... */
			size -= rd;
			if (!size) {
				/* 'size' bytes copied - all done */
				status = 0;
				break;
			}
		}
	}
out:
	return status ? -1 : total;
}

off_t bb_copyfd_eof(int fd1, int fd2)
{
	return bb_full_fd_action(fd1, fd2, 0);
}
/******************************************************************/
void ftp_die(const char *msg, const char *remote)
{
	/* Guard against garbage from remote server */
	const char *cp = remote;
	while (*cp >= ' ' && *cp < '\x7f') cp++;
	bb_error_msg_and_die("unexpected server response%s%s: %.*s\n",
			msg ? " to " : "", msg ? msg : "",
			(int)(cp - remote), remote);
//	assert(0);
}

int ftpcmd(const char *s1, const char *s2, FILE *stream, char *buf)
{
	unsigned n;
	if (s1) {
		if (s2) {
			fprintf(stream, "%s %s\r\n", s1, s2);
		} else {
			fprintf(stream, "%s\r\n", s1);
		}
	}
	do {
		char *buf_ptr;

		if (fgets(buf, 510, stream) == NULL) {
			bb_perror_msg_and_die("fgets");
			return -1;
		}
		buf_ptr = strstr(buf, "\r\n");
		if (buf_ptr) {
			*buf_ptr = '\0';
		}
	} while (!isdigit(buf[0]) || buf[3] != ' ');

	buf[3] = '\0';
	n = xatou(buf);
	buf[3] = ' ';
	return n;
}

void set_nport(len_and_sockaddr *lsa, unsigned port)
{
	if (lsa->sa.sa_family == AF_INET) {
		lsa->sin.sin_port = port;
		return;
	}
	/* What? UNIX socket? IPX?? :) */
}

int xconnect_ftpdata(ftp_host_info_t *server, char *buf)
{
	char *buf_ptr;
	unsigned short port_num;

	//printf("buf = %s\n", buf);
	/* Response is "NNN garbageN1,N2,N3,N4,P1,P2[)garbage]
	 * Server's IP is N1.N2.N3.N4 (we ignore it)
	 * Server's port for data connection is P1*256+P2 */
	buf_ptr = strrchr(buf, ')');
	if (buf_ptr) *buf_ptr = '\0';

	buf_ptr = strrchr(buf, ',');
	*buf_ptr = '\0';
	port_num = xatoul_range(buf_ptr + 1, 0, 255);

	buf_ptr = strrchr(buf, ',');
	*buf_ptr = '\0';
	port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
	
	//printf("#### port_num = %d\n", port_num);
	set_nport(server->lsa, htons(port_num));
	return xconnect_stream(server->lsa);
}

void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
{

	if (connect(s, s_addr, addrlen) < 0) {
		if (s_addr->sa_family == AF_INET)
			bb_perror_msg_and_die("%s (%s)\n",
					"cannot connect to remote host",
					inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr));
		bb_perror_msg_and_die("cannot connect to remote host\n");
//		assert(0);
	}
}

// Die with an error message if we can't open a new socket.
int xsocket(int domain, int type, int protocol)
{
	int r = socket(domain, type, protocol);

	if (r < 0) {
		/* Hijack vaguely related config option */
#if ENABLE_VERBOSE_RESOLUTION_ERRORS
		const char *s = "INET";
		if (domain == AF_PACKET) s = "PACKET";
		if (domain == AF_NETLINK) s = "NETLINK";
		USE_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
			bb_perror_msg_and_die("socket(AF_%s)", s);
#else
		bb_perror_msg_and_die("socket");
#endif
	}
	return r;
}

int xclose(int s)
{
	if (s > 0)
	{
		close(s);
		s = -1;
	}
}

int xconnect_stream(const len_and_sockaddr *lsa)
{
	int fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
	xconnect(fd, &lsa->sa, lsa->len);
	return fd;
}

FILE *ftp_login(ftp_host_info_t *server)
{
	FILE *control_stream;
	char buf[512];
	int login_fd;
	/* Connect to the command socket */
	login_fd = xconnect_stream(server->lsa);
	if(login_fd == -1)
		return NULL;
	
	control_stream = fdopen(login_fd, "r+");
	if (control_stream == NULL) {
		xclose(login_fd);
		/* fdopen failed - extremely unlikely */
		bb_perror_nomsg_and_die();
		return NULL;
	}
	if (ftpcmd(NULL, NULL, control_stream, buf) != 220) {
		ftp_die(NULL, buf);
		safe_fclose(control_stream);
		return NULL;
	}
	/*  Login to the server */
	switch (ftpcmd("USER", server->user, control_stream, buf)) {
		case 230:
			break;
		case 331:
			if (ftpcmd("PASS", server->password, control_stream, buf) != 230) {
				ftp_die("PASS", buf);
				safe_fclose(control_stream);
				return NULL;
			}
			break;
		default:
			{
				ftp_die("USER", buf);
				safe_fclose(control_stream);
				return NULL;
			}
	}
	if(ftpcmd("TYPE I", NULL, control_stream, buf) == -1)
	{
		safe_fclose(control_stream);
		return NULL;
	}
	return control_stream;
}

int ftp_mkdir(FILE *control_stream, const char *FoldName)
{
	if (strlen(FoldName) <= 0)
	{
		return -1;
	}
	char buf[512];
	int response = ftpcmd("MKD", FoldName, control_stream, buf);
	if(response != 257)
	{
		//printf("MKD1111111111111111111111:%d\n", response);
		ftp_die("MKD", buf);
		return -1;	
	}
	//printf("MKD2222222222222222222:%d\n", response);
	return 0;
}

int ftp_cd(FILE *control_stream, const char *FoldName)
{
	if (strlen(FoldName) <= 0)
	{
		return -1;
	}
	char buf[512];
	int response = ftpcmd("CWD", FoldName, control_stream, buf);
	if(response != 250)
	{
		//printf("CWD1111111111111111111111response:%d\n", response);
		ftp_die("CWD", buf);
		return -1;	
	}
	//printf("CWD2222222222222222222response:%d\n", response);
	return 0;
}

int ftp_send(ftp_host_info_t *server, FILE *control_stream,
		const char *server_path, char *local_path)
{
	struct stat sbuf;
	char buf[512];
	int fd_data;
	int fd_local;
	int response;

	/*  Connect to the data socket */
	if (ftpcmd("PASV", NULL, control_stream, buf) != 227) {
		ftp_die("PASV", buf);
		return -1;
	}
	fd_data = xconnect_ftpdata(server, buf);
	if(fd_data == -1)
		return -1;
	/* get the local file */
	fd_local = STDIN_FILENO;
	if (NOT_LONE_DASH(local_path)) {
		fd_local = xopen(local_path, O_RDONLY);
		while(fd_local == -1)
		{
			xclose(fd_local);
			sleep(1);
			fd_local = xopen(local_path, O_RDONLY);
		}
		fstat(fd_local, &sbuf);

		sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size);
		response = ftpcmd(buf, NULL, control_stream, buf);
		switch (response) {
			case 200:
			case 202:
				break;
			default:
				{
					xclose(fd_data);
					xclose(fd_local);
					ftp_die("ALLO", buf);
					return -1;
				}
		}
	}

	response = ftpcmd("STOR", server_path, control_stream, buf);
	switch (response) {
		case 125:
		case 150:
			break;
		default:
			{
				xclose(fd_data);
				xclose(fd_local);
				ftp_die("STOR", buf);
				return -1;
			}
	}

		
	/* transfer the file  */
	ftpmissions_t missionlist={0,0};
	ftpbackupmission_info_t filelist={0,0};
	do{
		do{
			if (bb_copyfd_eof(fd_local, fd_data) == -1) {
				/* close it all down */
				xclose(fd_data);
				xclose(fd_local);
				return -1;
			//exit(EXIT_FAILURE);
	 		 }
		}while(filelist.currfilelist_id++<=filelist.len_filelist);
	}while (missionlist.currmission_id++<=missionlist.len_missionlist);

	/* close it all down */
	close(fd_data);
	close(fd_local);
	if (ftpcmd(NULL, NULL, control_stream, buf) != 226) {
		ftp_die("close", buf);
		return -1;
	}
	return EXIT_SUCCESS;
}
int ftp_quit(FILE *control_stream)
{
	if (control_stream == NULL)
	{
		return -1;
	}
	char buf[512];
	ftpcmd("QUIT", NULL, control_stream, buf);
	safe_fclose(control_stream);
	return 0;
}

#if 1
int main(void)
{
	//const char *port = "ftp";
	FILE *control_stream;
	ftp_host_info_t *server;
	char local_path[128];
	char server_path[128];
	server = malloc(sizeof(*server));
	if (server == NULL)
	{
		return -1;
	}
	server->user = "ftpsvr";
	server->password = "123456";
	server->lsa = xhost2sockaddr("192.168.1.8", 21);
	printf("Connecting to %s (%s)\n", "192.168.1.8",
			xmalloc_sockaddr2dotted(&server->lsa->sa));
	control_stream = ftp_login(server);
	
	int iret = ftp_cd(control_stream, "screenshort10");
	if (iret < 0)
	{
		ftp_mkdir(control_stream, "screenshort10");
		ftp_cd(control_stream, "screenshort10");
	}
	
	while(1)
	{
		sprintf(local_path,  "%s", "100421133604-000-3-1.jpg");
		sprintf(server_path, "%s", "100421133604-000-3-1.jpg");
		if(ftp_send(server, control_stream, server_path, local_path)==-1)
		{
			fclose(control_stream);
			control_stream = NULL;
			printf("\nConnecting to %s (%s)\n", "192.168.1.8",
					xmalloc_sockaddr2dotted(&server->lsa->sa));
			while(control_stream == NULL)
			{
				server->user = "ftpsvr";
				server->password = "123456";
				server->lsa = xhost2sockaddr("192.168.1.8", 21);
				control_stream = ftp_login(server);
			}
		}
		else
		{
			//fprintf(stdout,"%s upload success\n",local_path);
		}
		ftp_quit(control_stream);
		break;
	}
	return 0;
}

#endif



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值