浅学C++(7)网络编程(ftp 客户端 代码实现)

连接服务器
[11:27:55] [R] 正在连接到 192.168.217.135 -> IP=192.168.217.135 PORT=21
[11:27:55] [R] 已连接到 192.168.217.135
[11:27:55] [R] 220 (vsFTPd 3.0.3)

发送用户名、密码
[11:27:55] [R] USER ubuntu
[11:27:55] [R] 331 Please specify the password.
[11:27:55] [R] PASS (hidden)
[11:27:55] [R] 230 Login successful.

pwd显示工作路径
[11:27:55] [R] PWD
[11:27:55] [R] 257 "/home/ubuntu" is the current directory

ls显示当前目录的详细信息
[11:27:55] [R] PASV
[11:27:55] [R] 227 Entering Passive Mode (192,168,217,135,202,198).     202*256+198=51910
[11:27:55] [R] 正在打开数据连接 IP: 192.168.217.135 端口: 51910
[11:27:55] [R] LIST -al
[11:27:55] [R] 150 Here comes the directory listing.
[11:27:55] [R] 226 Directory send OK.

cd进入目录
[11:29:01] [R] CWD Data
[11:29:01] [R] 250 Directory successfully changed.
[11:29:01] [R] PWD
[11:29:01] [R] 257 "/home/ubuntu/Data" is the current directory
[11:29:01] [R] PASV
[11:29:01] [R] 227 Entering Passive Mode (192,168,217,135,25,218).
[11:29:01] [R] 正在打开数据连接 IP: 192.168.217.135 端口: 6618
[11:29:01] [R] LIST -al
[11:29:01] [R] 150 Here comes the directory listing.
[11:29:01] [R] 226 Directory send OK.
[11:29:01] [R] 列表完成: 847 字节 耗时 0.02 秒 (0.8 KB/s)

mkdir 创建目录
[11:29:14] [R] MKD dir
[11:29:14] [R] 257 "/home/ubuntu/Data/dir" created

rmdir 删除空目录
[11:29:24] [R] RMD dir
[11:29:24] [R] 250 Remove directory operation successful.

get 下载文件 a.out
[11:29:52] [R] TYPE I
[11:29:52] [R] 200 Switching to Binary mode.
[11:29:52] [R] SIZE a.out
[11:29:52] [R] 213 12700
[11:29:52] [R] MDTM a.out
[11:29:52] [R] 213 20220822114225
[11:29:52] [R] PASV
[11:29:52] [R] 227 Entering Passive Mode (192,168,217,135,171,225).
[11:29:52] [R] 正在打开数据连接 IP: 192.168.217.135 端口: 44001
[11:29:52] [R] RETR a.out
[11:29:52] [R] 150 Opening BINARY mode data connection for a.out (12700 bytes).
[11:29:52] [R] 226 Transfer complete.


put上传文件lf.c
[11:30:09] [R] SIZE lf.c
[11:30:09] [R] 550 Could not get file size.
[11:30:09] [R] PASV
[11:30:09] [R] 227 Entering Passive Mode (192,168,217,135,76,34).
[11:30:09] [R] 正在打开数据连接 IP: 192.168.217.135 端口: 19490
[11:30:09] [R] STOR lf.c
[11:30:09] [R] 150 Ok to send data.
[11:30:09] [R] 226 Transfer complete.
[11:30:09] 上载: lf.c 182 字节 耗时 0.02 秒 (0.2 KB/s)
#ifndef FTPC_H
#define FTPC_H



//显示当前目录
void show_pwd(int sock,char* buf);

//创建空目录
void mk_dir(int sock,char* buf);

//删除空目录
void rm_dir(int sock,char* buf);

//进入目录
void cd_dir(int sock,char* buf);

//显示目录详细信息
void ls_dir(int sock,char* buf);

//上传
void up_file(int sock,char* buf);

//下载
void down_file(int sock,char* buf);

//退出
void quit_ftp(int sock);

#endif//FTPC_H





#include "ftpC.h"
#include "tools.h"


//显示当前目录
void show_pwd(int sock,char* buf)
{
	sprintf(buf,"PWD\n");
	send(sock,buf,strlen(buf),0);
	if(!num_judge(sock,257))
		printf("工作路径打开失败\n");
	return;
}

//创建空目录
void mk_dir(int sock,char* buf)
{
	char dir[256]={};
	sscanf(buf,"mkdir %s",dir);
	sprintf(buf,"MKD %s\n",dir);
	send(sock,buf,strlen(buf),0);
	if(!num_judge(sock,257))
		printf("目录创建失败\n");
	return;
}

//删除空目录
void rm_dir(int sock,char* buf)
{
	char dir[256]={};
	sscanf(buf,"rmdir %s",dir);
	sprintf(buf,"RMD %s\n",dir);
	send(sock,buf,strlen(buf),0);
	if(!num_judge(sock,250))
		printf("目录删除失败\n");
	return;	
}

//进入目录
void cd_dir(int sock,char* buf)
{
	char dir[256]={};
	sscanf(buf,"cd %s",dir);
	sprintf(buf,"CWD %s\n",dir);
	send(sock,buf,strlen(buf),0);
	if(!num_judge(sock,250))
	{
		printf("目录进入失败\n");
		return;
	}
	show_pwd(sock,buf);
	ls_dir(sock,buf);
}

//显示目录详细信息
void ls_dir(int sock,char* buf)
{
	int pasv_sock = open_data(sock);
	if(0 > pasv_sock)
		return;
	sprintf(buf,"LIST -al\n");
	send(sock,buf,strlen(buf),0);
	if(!num_judge(sock,150))
		return;
	while(read(pasv_sock,buf,4096))
	{
		printf("%s",buf);
		stdin->_IO_read_ptr = stdin->_IO_read_end;
	}
	if(!num_judge(sock,226));
		return;
	close(pasv_sock);
}

//上传
void up_file(int sock,char* buf)
{
	int pasv_sock = open_data(sock);
	char file[256]={};
	sscanf(buf,"put %s",file);
	sprintf(buf,"STOR %s\n",file);
	send(sock,buf,strlen(buf),0);
	int fd = open(file,O_RDONLY);
	if(0 > fd)
	{
		close(pasv_sock);
		printf("文件不存在,请检查!\n");
		return;
	}
	int ret = 0;
	while((ret = read(fd,buf,4096)))
	{
		send(pasv_sock,buf,ret,0);	
	}
	close(fd);
	close(pasv_sock);
	bzero(buf,4096);
	if(!num_judge(sock,150))
		return;
	bzero(buf,4096);
	if(!num_judge(sock,226))
		return;
	printf("文件上传成功!\n");	
}

//下载
void down_file(int sock,char* buf)
{
	
}

//退出
void quit_ftp(int sock)
{
	close(sock);
}
#ifndef TOOLS_H
#define TOOLS_H

#include <stdbool.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <getch.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

typedef struct sockaddr* SP;

struct sockaddr_in svr_addr;

char Argv[20];

//数字判断
bool num_judge(int sock,int num);

//密码隐藏
void secretword(char keye[]);

//登陆
int login_ftp(const char* argv);

//打开数据通道
int open_data(int sock);

#endif//TOOLS_H






#include "tools.h"


//数字判断
bool num_judge(int sock,int num)
{
	char buf[256]={};
	int ret = 0;
	recv(sock,buf,sizeof(buf),0);
	printf("%s",buf);
	sscanf(buf,"%d",&ret);
	if(num != ret)
		return false;
	return true;
}

//密码隐藏
void secretword(char keye[])
{
	stdin->_IO_read_ptr = stdin->_IO_read_end;
	unsigned char c;
	int i=0;//记录输入密码的个数
	while((c=getch())!='\n')//按下回车退出循环,否则获取键值
	{
		if(i<20 && isprint(c)) //判断密码是否小于20位并检查所传的字符是否可以打印
		{
			keye[i]=c;//密码一个一个存入数组
			i++;
			putchar('*');//打印一个*
		}
		else if(i>0 && c==127) //判断密码是否大于0位并按下删除键
		{
			i--;//密码个数减1
			putchar('\b'); //向前移动一位
			putchar(' '); //打印空格
			putchar('\b'); //再向前移动一位
		}
	}
	printf("\n");
	keye[i]='\0'; //最后输入'\0'
}

//登陆
int login_ftp(const char* argv)
{
	int cmd_sock = socket(AF_INET,SOCK_STREAM,0);
	if(0 > cmd_sock)
    	return -1;
	svr_addr.sin_family = AF_INET;
	svr_addr.sin_port = htons(21);
	svr_addr.sin_addr.s_addr = inet_addr(argv);
	socklen_t addrlen = sizeof(svr_addr);
	if(connect(cmd_sock,(SP)&svr_addr,addrlen))
    	return -1;
	char buf[255] = {};
	if(!num_judge(cmd_sock,220))
		return -1;
	char name[20] = {};
	printf("请输入用户名:");
	scanf("%s",name);
	sprintf(buf,"USER %s\n",name);
	send(cmd_sock,buf,strlen(buf),0);
	if(!num_judge(cmd_sock,331))
		return -1;
	char pass[20] = {};
	printf("请输入密码:");
 	secretword(pass);
	sprintf(buf,"PASS %s\n",pass);
	send(cmd_sock,buf,strlen(buf),0);
	if(!num_judge(cmd_sock,230))
		return -1;
	return cmd_sock;
}

//打开数据通道
int open_data(int sock)
{
	unsigned char ip1,ip2,ip3,ip4,port1,port2;
	char buf[256]={};
	int ret = 0;
	sprintf(buf,"PASV\n");
	send(sock,buf,strlen(buf),0);
	recv(sock,buf,sizeof(buf),0);
	sscanf(buf,"%d",&ret);
	if(227 != ret)
		return -1;
	sscanf(buf,"227 Entering Passive Mode (%hhu,%hhu,%hhu,%hhu,%hhu,%hhu)",&ip1,&ip2,&ip3,&ip4,&port1,&port2);
	char ip[16] = {};
	sprintf(ip,"%hhu.%hhu.%hhu.%hhu",ip1,ip2,ip3,ip4);
	unsigned short port = port1*256+port2;
	printf("%s\n%hu\n",buf,port);
	int pasv_sock = socket(AF_INET,SOCK_STREAM,0);
	if(0 > pasv_sock)
		return -1;
	struct sockaddr_in pasv_addr = {};
	pasv_addr.sin_family = AF_INET;
	pasv_addr.sin_port = htons(port);
	pasv_addr.sin_addr.s_addr = inet_addr(ip);
	socklen_t addrlen = sizeof(pasv_addr);
	if(connect(pasv_sock,(SP)&pasv_addr,addrlen))
	{
		printf("连接数据通道失败\n");
		return -1;
	}
	return pasv_sock;
}
#include "ftpC.h"
#include "tools.h"

int main(int argc,const char* argv[])
{
	strcpy(Argv,argv[1]);
	int sock = login_ftp(Argv);
	if(0 > sock)
	{
		printf("登陆失败\n");
		return 0;
	}
	printf("登陆成功\n");
	char buf[4096] = {};
	size_t buf_size = sizeof(buf);
	while((scanf("%[^\n]%*c",buf) || 1) && strcmp(buf,"quit") && strcmp(buf,"bye"))
	{
		if(!strncmp(buf,"pwd",3))
			show_pwd(sock,buf);
		else if(!strncmp(buf,"mkdir ",6))
			mk_dir(sock,buf);
		else if(!strncmp(buf,"rmdir ",6))
			rm_dir(sock,buf);
		else if(!strncmp(buf,"cd ",3))
			cd_dir(sock,buf);
		else if(!strncmp(buf,"ls ",3))
			ls_dir(sock,buf);
		else if(!strncmp(buf,"put ",4))
			up_file(sock,buf);
		else if(!strncmp(buf,"get ",4))
			down_file(sock,buf);
		else
		{
			printf("非法命令\n");
			stdin->_IO_read_ptr = stdin->_IO_read_end;
		}
		bzero(buf,buf_size);
	}
	quit_ftp(sock);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在静态方法中使用JdbcTemplate需要注意以下几点: 1. 静态方法中无法直接使用Spring容器中的Bean,因为静态方法是类级别的,而Bean是实例级别的。因此需要手动获取JdbcTemplate实例,可以通过ApplicationContext获取JdbcTemplate实例,或者通过静态变量保存JdbcTemplate实例。 2. 在使用JdbcTemplate时,需要先创建一个JdbcTemplate实例,并设置数据源。数据源可以通过Spring容器注入,或者手动创建。在静态方法中,可以通过静态变量保存JdbcTemplate实例,避免重复创建。 3. 在使用JdbcTemplate操作数据库时,需要注意线程安全问题。JdbcTemplate是线程安全的,但是需要保证JdbcTemplate实例的线程安全,即在多线程环境中需要保证同一JdbcTemplate实例不会被并发访问。 下面是一个示例代码: ``` public class JdbcUtils { private static JdbcTemplate jdbcTemplate; public static void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } public static void executeSql(String sql) { jdbcTemplate.execute(sql); } } ``` 在上面的代码中,我们通过静态变量保存了JdbcTemplate实例,并提供了一个静态方法setDataSource用于设置数据源。在使用JdbcTemplate时,我们可以直接调用静态方法executeSql执行SQL语句。需要注意的是,这里的executeSql方法是线程安全的,因为JdbcTemplate实例是共享的,并且JdbcTemplate本身是线程安全的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值