概述
题目
简单FTP客户端软件开发(100分)网络环境中的一项基本应用就是将文件从一台计算机中复制到另一台可能相距很远的计算机中。而文件传送协议FTP是因特网上使用得最广泛的文件传送协议。FTP使用客户服务器方式。
设计要求:
1)以命令行形式运行
2)该FTP客户端程序具有以下基本功能:能完成FTP链接的打开和关闭操作;能执行文件的上传和下载;能完成目录的创建、删除等有关操作。
3)设计中加入新的功能:登录,进入上级或下级目录
要求可以传输简单的文本文件。
设计思路
1、分为两个端口,指令交流端口,数据交换端口
2、指令端口连接后一直保持通信,直到获得退出信号
3、数据交换端口在获得相关指令后重新建立连接
使用方法
1、分别创建两个C++项目
2、复制代码进入即可
3、若两个都在本地,使用本地回环测试IP,127.0.0.1
4、登录的部分在客户端中被注释掉了没有开启
Tips:
目前登录以及help部分仍有两个小bug,系由端口的命令断开以及连接部分引起,交由读者自己研究,若不想管可以不使用这两个功能
服务端——>Server
#include "Winsock2.h"
#include "windows.h"
#include <iostream>
#include <string>
using namespace std;
#define RECV_PORT 3312 //接收端口
#define SEND_PORT 4302 //发送端口
#define DATA_PORT 3313 //数据发送端口
#pragma comment(lib, "wsock32.lib")
SOCKET sockClient, sockServer;
SOCKET dataClient, dataServer;
sockaddr_in dataAddr;
sockaddr_in severAddr;//服务器地址
sockaddr_in ClientAddr;//客户端地址
sockaddr_in dataClientAddr;//数据地址
int addrLen; //地址长度
char fileName[20]; //文件名
char order[20]; //命令
char rbuff[1024]; //接收缓冲区
char sbuff[1024]; //发送缓冲区
char namePassword[1024] = "user 123456"; //用户名和密码
//***************函数声明***************
DWORD startSock();
DWORD createSocket();
int sendFileRecord(SOCKET datatcps, WIN32_FIND_DATA *pfd);
int sendFileList(SOCKET datatcps);
int sendFile(SOCKET datatcps, FILE* file);
DWORD connectProcess();
//***************函数声明***************
DWORD startSock() {//初始化winsock
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) {
cout << "初始化失败" << endl;
return -1;
}
return 1;
}
DWORD createSocket() {
sockClient = socket(AF_INET, SOCK_STREAM, 0);
dataClient = socket(AF_INET, SOCK_STREAM, 0);
if (sockClient == SOCKET_ERROR||dataClient == SOCKET_ERROR) {
cout << "创建失败" << endl;
WSACleanup();
return -1;
}
dataAddr.sin_family = AF_INET;
severAddr.sin_family = AF_INET;
dataAddr.sin_addr.s_addr = htonl(INADDR_ANY);//监听任意地址
dataAddr.sin_port = htons(DATA_PORT);
severAddr.sin_addr.s_addr = htonl(INADDR_ANY);//监听任意地址
//cout<<htonl(INADDR_ANY)<<endl;
severAddr.sin_port = htons(RECV_PORT);
if (bind(sockClient, (struct sockaddr FAR*)&severAddr, sizeof(severAddr)) == SOCKET_ERROR||bind(dataClient, (struct sockaddr FAR*)&dataAddr, sizeof(dataAddr)) == SOCKET_ERROR) {
//bind函数用于将socket和地址结构绑定==
cout << "绑定失败" << endl;
return -1;
}
return 1;
}
DWORD mkdir(char fileName[]){
char path[1000];
GetCurrentDirectory(sizeof(path), path);//找到当前进程的当前目录
strcat(path,"\");
strcat(path,fileName);
cout<<path<<endl;
bool flag = CreateDirectory(path,NULL);
if (flag)
cout<<"创建文件:"<<fileName<<"成功"<<endl;
else
cout<<"创建文件:"<<fileName<<"失败"<<endl;
}
DWORD delFile(char fileName[]){
char path[1000];
GetCurrentDirectory(sizeof(path), path);//找到当前进程的当前目录
strcat(path,"\");
strcat(path,fileName);
// cout<<path<<endl;
bool flag = RemoveDirectory(path);
if (flag)
cout<<"删除文件:"<<fileName<<"成功"<<endl;
else
cout<<"删除文件:"<<fileName<<"失败"<<endl;
}
DWORD connectProcess() {
addrLen = sizeof(ClientAddr);//addrLen是对象地址的长度
if (listen(sockClient, 10) < 0|| listen(dataClient, 10)<0) {//让套接字进入被动监听状态,参数2为请求队列的最大长度
cout << "监听失败" << endl;
return -1;
}
cout << "服务器正在监听中…" << endl;
while (1) {
//accept取出队列头部的连接请求
//sockclient是处于监听的套接字
//ClientAddr 是监听的对象地址
sockServer = accept(sockClient, (struct sockaddr FAR*)&ClientAddr, &addrLen);
while (1) {
memset(rbuff, 0, sizeof(rbuff));
memset(sbuff, 0, sizeof(sbuff));
if (recv(sockServer, rbuff, sizeof(rbuff), 0) <= 0) {
continue;
}
cout << endl << "获取并执行的命令:" << rbuff << endl;
if (strncmp(rbuff, "get", 3) == 0) {//将文件发给客户端
strcpy(fileName, rbuff + 4);
FILE* file;//定义一个文件访问指针
//处理下载文件请求
file = fopen(fileName, "rb");//二进制打开文件,只允许读
if (file) {
sprintf(sbuff, "get %s", fileName);
if (!send(sockServer, sbuff, sizeof(sbuff), 0)) {
cout<<"发送失败"<<endl;
fclose(file);
return 0;
}
else {//创建额外数据连接传送数据
if (!sendFile(dataClient, file)) {
return 0;
}
fclose(file);
}
}else {
strcpy(sbuff, "无法打开文件n");
cout<<"无法打开文件"<<endl;
if (!send(sockServer, sbuff, sizeof(sbuff), 0)) {
return 0;
}
}
}//get
else if (strncmp(rbuff, "put", 3) == 0) {//从客户端上传上来文件
cout<<"debug1"<<endl;
FILE* fd;
int cnt;
strcpy(fileName, rbuff + 4);
fd = fopen(fileName, "wb");
if (fd == NULL) {
cout << "无法打开文件" << fileName << endl;
return 0;
}
sprintf(sbuff, "put %s", fileName);
if (!send(sockServer, sbuff, sizeof(sbuff), 0)) {
fclose(fd);
return 0;
}
memset(sbuff, '