当前位置 博文首页 > socket实现miniftp,C++ socket实现miniftp的方法

    socket实现miniftp,C++ socket实现miniftp的方法

    作者:xiaoyingying 时间:2021-08-11 15:45

        IIS7批量FTP管理功能说明:
        1、可批量导入,导出FTP信息
        2、其他ftp工具有的功能,我们也有
        3、特色功能:可以定时上传下载
        4、数据信息列表化、一眼就能知道那个是那个
        5、批量连接标签页式切换方便快捷
        6、7大连接模式更多好的兼容
        7、内嵌编辑器有效解决普通txt记事本乱码
        8、锁屏功能当程序有规定时间内没人操作,则自动锁程序。输入密码才可以正常操作
        本产品适用于:懒得记录FTP信息和有批量定时备份,上传下载的运维或站长。
        下载地址:http://ftp.iis7.com/
        图片:
        建立连接
        连接使用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
    上一篇:没有了
    下一篇:没有了