IIS7批量FTP管理功能说明:
1、可批量导入,导出FTP信息
2、其他ftp工具有的功能,我们也有
3、特色功能:可以定时上传下载
4、数据信息列表化、一眼就能知道那个是那个
5、批量连接标签页式切换方便快捷
6、7大连接模式更多好的兼容
7、内嵌编辑器有效解决普通txt记事本乱码
8、锁屏功能当程序有规定时间内没人操作,则自动锁程序。输入密码才可以正常操作
本产品适用于:懒得记录FTP信息和有批量定时备份,上传下载的运维或站长。
图片:
建立连接
连接使用TCP连接,服务器和客户端分别创建自己的套接字一端,服务器等待连接,客户端发起连接(并指定服务器ip)。在两者端口号一致且不被占用的情况下,连接建立。
在整个过程中,服务器对每一个来访的客户端建立一个连接,在客户未请求与服务器断开时,该连接一直存在,用户可以不断向服务器发出请求。(持久性、流水线型连接)
客户端断开后,关闭客户端的套接字部分,服务器继续等待新的连接。服务器一次只能处理一个客户端的连接,不支持并发访问。
PDU格式
由于ftp应当支持几乎任意类型文件,而几乎所有类型文件都能用二进制来解析,所以我们采用了二进制的格式来读取以及写入文件。在整个过程中,我们并不关心文件的具体内容,也无需在程序中解析文件,而是将其当作数据流看待。
受到缓存区大小的限制,我们无法一次性传输整个文件,所以我们将文件按缓存区大小拆分成数据包分批发送,我们可以将数据及时从缓存区写入文件,这样就让出了缓存区空间。数据包仅仅包含数据,不包含头部或尾部信息。
此外,接收文件时,recv()函数将会循环调用,因此,我们需要一个信号来通知什么时候发送完毕。
一个想法是发送终止信号,这是可行的,但更好的方法是在一开始发送文件总字节数,让接收方根据剩余字节大小判断什么时候接收完毕。因为在写入文件时,我们需要指定写入的字节数,尤其是在发来的数据流字节数不等于缓冲区大小时。写入字节数的错误会导致文件受损。
接收确认
我们知道TCP是可靠传输协议,它采取了一系列措施来保证传输不会出错。所以在使用TCP连接时,我们相信数据在链路层上没有出差错,它一定会成功发送到对方手上。但是在客户端接收服务器发来的文件的时候,我们仍然需要服务器发来确认信息。原因在于,虽然我们可以保证链路层不出错,但是我们无法保证应用层不出错。例如,客户端可能会给出错误的文件名,因为接收不到服务器发来的信息,所以会陷入空等状态。
ftpClient.h
#pragma
#include<winsock.h>
classftpClient
{
private:
enum{
SERVER_PORT=9999,
BUFFER_SIZE=4096
};
sockaddr_inserverChannel;
charbuffer[BUFFER_SIZE];
intserverSocket;
intclientSocket;
boolisConnect;
charname[50];
boolgetFile();
boolputFile();
boolacknowledge();
boolsendRequest(char*instruction);
boolconnect2Host(constchar*hostName);
boolgetWorkDir();
public:
ftpClient();
~ftpClient();
voidstart();
};
ftpClient.cpp
#define_CRT_SECURE_NO_WARNINGS
#include"ftpClient.h"
#include<cstdio>
#include<io.h>
#include<cstring>
#include<fstream>
ftpClient::ftpClient()
{
WORDwVersionRequested;
WSADATAwsaData;
intret;
//WinSock初始化:
wVersionRequested=MAKEWORD(2,2);//希望使用的WinSockDLL的版本
ret=WSAStartup(wVersionRequested,&wsaData);
if(ret!=0)
{
printf("WSAStartup()failed!\n");
}
//确认WinSockDLL支持版本2.2:
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf("InvalidWinsockversion!\n");
}
isConnect=false;
}
voidftpClient::start()
{
charc[100];
chard[100];
printf("这里是FTP客户端,您可以输入help查看操作方法,输入quit退出客户端\n");
while(1){
scanf("%s",c);
if(strcmp(c,"help")==0){
printf("get[fileName]--下载文件\n"
"put[fileName]--上传文件\n"
"ftp[ip]--登录FTP\n"
"pwd--显示服务器当前工作文件夹\n"
"cd[dirName]--更改当前文件夹\n"
"close--关闭与当前ftp的连接\n"
"quit--退出客户端\n"
);
}
elseif(strcmp(c,"get")==0){
scanf("%s",d);
strcat(c,"");
strcat(c,d);
if(!isConnect){
printf("youhaven'tconnectedtoanyserver!\n");
}
elsesendRequest(c);
}
elseif(strcmp(c,"put")==0){
scanf("%s",d);
strcat(c,"");
strcat(c,d);
if(!isConnect){
printf("youhaven'tconnectedtoanyserver!\n");
}
elsesendRequest(c);
}
elseif(strcmp(c,"ftp")==0){
scanf("%s",d);
if(!isConnect&&connect2Host(d)){
isConnect=true;
}
elseif(isConnect){
printf("youhavealreadyconnectedtoserver\n"
"pleaseclosetheconnectionbeforeconnecttoanewserver\n");
}
}
elseif(strcmp(c,"pwd")==0){
if(!isConnect){
printf("youhaven'tconnectedtoanyserver!\n");
}
elsesendRequest(c);
}
elseif(strcmp(c,"cd")==0){
scanf("%s",d);
strcat(c,"");
strcat(c,d);
if(!isConnect){
printf("youhaven'tconnectedtoanyserver!\n");
}
elsesendRequest(c);
}
elseif(strcmp(c,"quit")==0){
if(isConnect){
strcpy(c,"close");
isConnect=false;
send(clientSocket,c,strlen(c)+1,0);
closesocket(clientSocket);
}
break;
}
elseif(strcmp(c,"close")==0){
if(isConnect){
isConnect=false;
send(clientSocket,c,strlen(c)+1,0);
closesocket(clientSocket);
}
}
else{
printf("syntexerror\n");
}
}
}
boolftpClient::connect2Host(constchar*hostName)
{
//创建socket
clientSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(clientSocket<0){
printf("cannotcreatesocket\n");
returnfalse;
}
elseprintf("successfullycreatesocket\n");
memset(&serverChannel,0,sizeof(serverChannel));//初始化为0
serverChannel.sin_family=AF_INET;//channel协议家族AF_INET
serverChannel.sin_addr.S_un.S_addr=inet_addr(hostName);//地址
serverChannel.sin_port=htons(SERVER_PORT);//服务器端口
//建立连接
serverSocket=connect(clientSocket,(sockaddr*)&serverChannel,sizeof(serverChannel));
if(serverSocket<0){
printf("cannotconnecttothehost\n");
returnfalse;
}
else{
printf("successfullyconnecttothehost\n");
returntrue;
}
}
boolftpClient::sendRequest(char*instruction)
{
intr=send(clientSocket,instruction,strlen(instruction)+1,0);
if(r==SOCKET_ERROR){
printf("requestfailed\n");
returnfalse;
}
else{
printf("requestsuccess\n");
charopt[5];
inti=0,j=0;
while(instruction[i]!=''&&instruction[i]!='\0'){
opt[i]=instruction[i];
i++;
}
opt[i]='\0';
i++;
while(instruction[i]!='\0'){
name[j]=instruction[i];
i++,j++;
}
name[j]='\0';
if(strcmp(opt,"get")==0){
if(getFile()){
printf("successfullydownload\n");
}
elseprintf("downloadfailed\n");
}
elseif(strcmp(opt,"put")==0){
if(putFile()){
printf("successfullyupload\n");
}
elseprintf("uploadfailed\n");
}
elseif(strcmp(opt,"pwd")==0){
if(!getWorkDir())
printf("getworkdirectoryfailed\n");
}
elseif(strcmp(opt,"cd")==0){
printf("operationfinished\n");
}
else{
printf("syntexerror\n");
returnfalse;
}
returntrue;
}
}
boolftpClient::getFile()
{
memset(buffer,0,sizeof(buffer));
intret;
charlength[20];
ret=recv(clientSocket,length,sizeof(length),0);
if(ret==SOCKET_ERROR){
returnfalse;
}
elseif(strcmp(length,"NAK")==0){
returnfalse;
}
intsize=atoi(length);
std::ofstreamout;
out.open(name,std::ios::binary);
if(!out){
printf("cannotsavethefile\n");
returnfalse;
}
while(size>0){
ret=recv(clientSocket,buffer,BUFFER_SIZE,0);
ints=size<BUFFER_SIZE?size:BUFFER_SIZE;
if(ret==SOCKET_ERROR){
out.close();
returnfalse;
}
elseif(strcmp(buffer,"NAK")==0){
out.close();
returnfalse;
}
else{
out.write(buffer,s);
}
size-=BUFFER_SIZE;
}
out.close();
returnacknowledge();
}
boolftpClient::putFile()
{
std::ifstreamin;
//打开文件
in.open(name,std::ios::binary);
if(!in){
printf("cannotopenthefile\n");
returnfalse;
}
memset(buffer,0,sizeof(buffer));
//得到文件的字节数
in.seekg(0,std::ios_base::end);
intsp=in.tellg();
inttotal_size=0;
intr;
charlength[20];
sprintf(length,"%d",sp);
//发送字节
r=send(clientSocket,length,sizeof(length),0);
if(r==SOCKET_ERROR){
returnfalse;
}
while(sp>0){
in.clear();
in.seekg(total_size,std::ios_base::beg);
memset(buffer,0,sizeof(buffer));
//读取文件
in.read(buffer,sizeof(buffer));
intsize=sp<BUFFER_SIZE?sp:BUFFER_SIZE;
total_size+=size;
//发送文件
r=send(clientSocket,buffer,size,0);
sp-=size;
if(r==SOCKET_ERROR){
in.close();
returnfalse;
}
}
in.close();
}
boolftpClient::getWorkDir(){
printf("getWorkDir\n");
memset(buffer,0,sizeof(buffer));
intret;
charlength[20];
ret=recv(clientSocket,length,sizeof(length),0);
if(ret==SOCKET_ERROR){
returnfalse;
}
intsize=atoi(length);
while(size>0){
ret=recv(clientSocket,buffer,BUFFER_SIZE,0);
if(ret==SOCKET_ERROR){
returnfalse;
}
else{
printf("%s",buffer);
}
size-=BUFFER_SIZE;
}
returntrue;
}
boolftpClient::acknowledge()
{
intret=recv(clientSocket,buffer,BUFFER_SIZE,0);
if(ret>0){
if(strcmp(buffer,"NAK")==0)returnfalse;
elseif(strcmp(buffer,"ACK")==0)returntrue;
}
}
ftpClient::~ftpClient()
{
if(isConnect){
isConnect=false;
charc[6];
strcpy(c,"close");
send(clientSocket,c,strlen(c)+1,0);
closesocket(clientSocket);
}
}
main.cpp
#define_CRT_SECURE_NO_WARNINGS
#define_WINSOCK_DEPRECATED_NO_WARNINGS
#pragma(lib,"ws2_32.lib")
#include"ftpClient.h"
#include<stdio.h>
intmain()
{
ftpClienta;
a.start();
return0;
}
ftpServer.h
#pragmaonce
#include<winsock.h>
classftpServer
{
private:
enum{
SERVER_PORT=9999,
BUFFER_SIZE=4096,
QUEUE_SIZE=10
};
charbuffer[BUFFER_SIZE];
sockaddr_inserverChannel;
charname[50];
charworkDir[100];//storelikeC:\UsersMARK:字符串末没有斜线!!
intserverSocket;//socket
intclientSocket;
boolsendFile();
boolreceiveFile();
booldoPwd();
booldoCd();
boolisValidPath(char*path);
public:
ftpServer();
boolstart();//开启服务器
};
ftpServer.cpp
#define_CRT_SECURE_NO_WARNINGS
#include"ftpServer.h"
#include<cstdio>
#include<cstdlib>
#include<fstream>
#include<cstring>
ftpServer::ftpServer()
{
WORDwVersionRequested;
WSADATAwsaData;
intret;
//WinSock初始化:
wVersionRequested=MAKEWORD(2,2);//希望使用的WinSockDLL的版本
ret=WSAStartup(wVersionRequested,&wsaData);
if(ret!=0)
{
printf("WSAStartup()failed!\n");
}
//确认WinSockDLL支持版本2.2:
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
WSACleanup();
printf("InvalidWinsockversion!\n");
}
//workDir初始化为当前路径
system("cd>tempFile");
std::ifstreamin("tempFile",std::ifstream::in);
in>>workDir;
in.close();
}
boolftpServer::start()
{
inton=1;
//初始化服务器
memset(&serverChannel,0,sizeof(serverChannel));
serverChannel.sin_family=AF_INET;
serverChannel.sin_addr.s_addr=htonl(INADDR_ANY);
serverChannel.sin_port=htons(SERVER_PORT);
//创建套接字
this->serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(serverSocket<0){
printf("cannotcreatesocket\n");
returnfalse;
}
elseprintf("successfullycreatesocket\n");
setsockopt(serverSocket,SOL_SOCKET,SO_REUSEADDR,
(char*)&on,sizeof(on));
//绑定
intb=bind(serverSocket,(sockaddr*)&serverChannel,
sizeof(serverChannel));
if(b<0){
printf("binderror\n");
returnfalse;
}
elseprintf("successfullybind\n");
//监听
intl=listen(serverSocket,QUEUE_SIZE);
if(l<0){
printf("listenfailed\n");
returnfalse;
}
elseprintf("successfullylisten\n");
intlen=sizeof(serverChannel);
//服务器等待连接
while(1){
printf("waitingforconnection...\n");
//接受一个连接
clientSocket=accept(serverSocket,(sockaddr*)&serverChannel,
&len);
if(clientSocket<0){
printf("acceptfailed\n");
}
else{
printf("successfullyconnect\n");
while(1){
memset(buffer,0,sizeof(buffer));
intret;
ret=recv(clientSocket,buffer,BUFFER_SIZE,0);
if(ret==SOCKET_ERROR){
printf("receivefailed\n");
}
else{
charopt[50];
printf("successfullyreceive\n");
inti=0,j=0;
printf("buffer=%s\n",buffer);
while(buffer[i]!=''&&buffer[i]!='\0'){
opt[i]=buffer[i];
i++;
}
opt[i]='\0';
if(buffer[i]!='\0'){
i++;
}
while(buffer[i]!='\0'){
name[j]=buffer[i];
i++,j++;
}
name[j]='\0';
if(strcmp(opt,"get")==0){
charret[4];
if(!sendFile()){
strcpy(ret,"NAK");
send(clientSocket,ret,sizeof(ret),0);
}
else{
strcpy(ret,"ACK");
send(clientSocket,ret,sizeof(ret),0);
}
}
elseif(strcmp(opt,"put")==0){
receiveFile();
}
elseif(strcmp(opt,"pwd")==0){
doPwd();
}
elseif(strcmp(opt,"cd")==0){
doCd();
}
elseif(strcmp(opt,"close")==0){
break;
}
else{
printf("syntexerror\n");
}
}
}
}
}
returntrue;
}
boolftpServer::sendFile()
{
std::ifstreamin;
charpath[100];
strcpy(path,workDir);
strcat(path,"\\");
strcat(path,name);
in.open(path,std::ios::binary);
if(!in){
printf("cannotopenthefile\n");
returnfalse;
}
memset(buffer,0,sizeof(buffer));
in.seekg(0,std::ios_base::end);
intsp=in.tellg();
inttotal_size=0;
intr;
charlength[20];
sprintf(length,"%d",sp);
r=send(clientSocket,length,sizeof(length),0);
if(r==SOCKET_ERROR){
printf("sendfailed\n");
returnfalse;
}
else{
printf("sendsuccess\n");
}
while(sp>0){
in.clear();
in.seekg(total_size,std::ios_base::beg);
memset(buffer,0,sizeof(buffer));
in.read(buffer,sizeof(buffer));
intsize=sp<BUFFER_SIZE?sp:BUFFER_SIZE;
total_size+=size;
r=send(clientSocket,buffer,size,0);
sp-=size;
if(r==SOCKET_ERROR){
printf("sendfailed\n");
returnfalse;
}
else{
printf("sendsuccess\n");
}
}
in.close();
returntrue;
}
boolftpServer::receiveFile()
{
charpath[100];
strcpy(path,workDir);
strcat(path,"\\");
strcat(path,name);
memset(buffer,0,sizeof(buffer));
intret;
charlength[20];
ret=recv(clientSocket,length,sizeof(length),0);
if(ret==SOCKET_ERROR){
printf("receivefailed\n");
returnfalse;
}
else{
printf("successfullyreceive\n");
}
intsize=atoi(length);
std::ofstreamout;
out.open(path,std::ios::binary);
if(!out){
printf("cannotsavethefile\n");
returnfalse;
}
while(size>0){
ints=size<BUFFER_SIZE?size:BUFFER_SIZE;
ret=recv(clientSocket,buffer,BUFFER_SIZE,0);
if(ret==SOCKET_ERROR){
printf("receivefailed\n");
break;
}
else{
printf("successfullyreceive\n");
out.write(buffer,s);
}
size-=BUFFER_SIZE;
}
out.close();
returntrue;
}
boolftpServer::doPwd(){
chartemCMD[150];
memset(temCMD,0,sizeof(temCMD));
strcat(temCMD,"echo");
strcat(temCMD,workDir);
strcat(temCMD,">tempFile");
system(temCMD);
memset(temCMD,0,sizeof(temCMD));
strcat(temCMD,"dir/b");
strcat(temCMD,workDir);
strcat(temCMD,">>tempFile");
system(temCMD);
std::ifstreamin("tempFile",std::fstream::in);
if(!in){
printf("cannotopenthefile\n");
returnfalse;
}
memset(buffer,0,sizeof(buffer));
in.seekg(0,std::ios_base::end);
intsp=in.tellg();
inttotal_size=0;
intr;
charlength[20];
sprintf(length,"%d",sp);
r=send(clientSocket,length,sizeof(length),0);
if(r==SOCKET_ERROR){
printf("sendfailed\n");
returnfalse;
}
else{
printf("sendsuccess\n");
}
while(sp>0){
in.clear();
in.seekg(total_size,std::ios_base::beg);
memset(buffer,0,sizeof(buffer));
in.read(buffer,sizeof(buffer));
intsize=sp<BUFFER_SIZE?sp:BUFFER_SIZE;
total_size+=size;
printf("transfersize=%d\n",total_size);
r=send(clientSocket,buffer,size,0);
sp-=size;
if(r==SOCKET_ERROR){
printf("sendfailed\n");
returnfalse;
}
else{
printf("sendsuccess\n");
}
}
in.close();
returntrue;
}
boolftpServer::isValidPath(char*path){
chartemCMD[100];
memset(temCMD,0,sizeof(temCMD));
strcat(temCMD,"cd");
strcat(temCMD,path);
intres=system(temCMD);
returnres==0;
}
boolftpServer::doCd(){
for(inti=0;name[i]!='\0';++i){
if(name[i]=='/')
name[i]='\\';
}
if(name[0]=='.'&&name[1]=='.'){
chartemDir[100];
strcpy(temDir,workDir);
for(inti=sizeof(temDir);i>=0;--i){
if(temDir[i]=='\\'){
temDir[i]='\0';
break;
}
}
strcat(temDir,name+2);
if(isValidPath(temDir)){
strcpy(workDir,temDir);
}
else{
returnfalse;
}
}
elseif(name[0]=='.'&&name[1]!='.'){
chartemDir[100];
strcpy(temDir,workDir);
strcat(temDir,name+1);
if(isValidPath(temDir)){
strcpy(workDir,temDir);
}
else{
returnfalse;
}
}
elseif(name[1]==':'){
if(isValidPath(name)){
strcpy(workDir,name);
}
else{
returnfalse;
}
}
else{
chartemDir[100];
strcpy(temDir,workDir);
strcat(temDir,"\\");
strcat(temDir,name);
if(isValidPath(temDir)){
strcpy(workDir,temDir);
}
else{
returnfalse;
}
}
returntrue;
}
main.cpp
#include"ftpServer.h"
#pragma(lib,"ws2_32.lib")
intmain()
{
ftpServerf;
f.start();
}
原文链接:https://blog.csdn.net/ZJU_fish1996/article/details/52983577