FTP上传的实现

对于文件的读写不太熟悉,犯了很多错误。服务器

好比,对于传送的文件中有各类文件,刚开始时用的r打开,只能实现txt文件的传输,而且传输后获得的文件的格式与源文件不一致。还有对于fgets与fread不太了解。并发


  • fget:tcp

函数原型:char *fgets(char *string, int n, FILE *fp);ide

头文件:#include<stdio.h>函数

是不是标准函数:是测试

函数功能:从fp所指的文件中读取一个长度为(n-1)的字符串,并将该字符串存入以string为起始地址的缓冲区中。fgets函数有三个参数,其中string为缓冲区首地址,n规定了要读取的最大长度,fp为文件指针。ui

返回值:返回地址string,若遇到文件结束符或出错,返回NULL。用feof ferror判断是否出错。spa


  • fread:指针

函数原型:int fread(void *buf, int size, int count, FILE *fp);调试

头文件:#include<stdio.h>

是不是标准函数:是

函数功能:从fp指向的文件中读取长度为size count个数据项,并将它输入到以buf为首地址的缓冲区中。此时,文件指针fp会自动增长实际读入数据的字节数,即fp指向最后读入字符的下一个字符位置。

返回值:返回实际读入数据项的个数,即count值。若遇到错误或文件结束返回0


  • fwrite:

函数原型:int fwrite(void *buf, int size, int count, FILE *fp);

头文件:#include<stdio.h>

是不是标准函数:是

函数功能:将buf所指向的count*size个字节的数据输出到文件指针fp所指向的文件中去。该函数与fread相对,输出数据后,文件指针fp自动指向输出的最后一个字符的下一个位置。该函数经常使用于分批将数据块输出到文件中。

返回值:返回实际写入文件数据项个数。




在个人使用过程当中感觉是对获取的字符串处理则用fgets,连续读取文件则使用fread。



#include "sock_class.h"
#define  RESPONSE_BUF_SIZE  4096
#define  DATA_BUF_SIZE      4096
int FtpPut(const char* szIP, const char* szPath, const char* szFile);
int main(int argc, char *argv[])
{
    char szData[4096];
    if (argc < 4)
    {
        printf("USAGE: %s IP Path File", argv[0]);
        return 1;
    }
    if (WinSockInit() != 0)
    {
        printf("WSAStartup failed with error \n");
        return 1;
    }
    int nRet = FtpPut(argv[1], argv[2], argv[3]);
                                                                                                                                                                          
    WSACleanup();
    return nRet;
}
//处理响应信息
int GetFtpReponse(tcp_sock& sockCtrl, char* szRespBuf, int nLen)
{
    int nRetCode;
    if (sockCtrl.read_line(szRespBuf, nLen) == SOCKET_ERROR)
    {
        printf("GetFtpReponse error!\n");
        return 0;
    }
    printf(szRespBuf);
    if (sscanf(szRespBuf, "%ld", &nRetCode) != 1)
    {
        printf("GetFtpReponse error(%s)!\n", szRespBuf);
        return 0;
    }
    if (szRespBuf[3] == '-')
    {
        do
        {
            if (sockCtrl.read_line(szRespBuf, nLen) == SOCKET_ERROR)
            {
                printf("GetFtpReponse error!\n");
                return 0;
            }
            if ((szRespBuf[0] >= '0') && (szRespBuf[0] <= '9'))
            {
                break;
            }
        }
        while (1);
    }
                                                                                                                                                                           
    return nRetCode;
}
//发控制信息
int SendFtpCmd(tcp_sock& sockCtrl, const char* szCmd)
{
    if (sockCtrl.write_line(szCmd, strlen(szCmd)) == SOCKET_ERROR)
    {
        printf("SendFtpCmd error(%s)!\n", szCmd);
        return 0;
    }
    return 1;
}
//链接Ftp服务器
int ConnectFtp(tcp_sock& sockCtrl, const char* szIP)
{
    char    szRespBuf[RESPONSE_BUF_SIZE + 1];
    if (!sockCtrl.connect(szIP, "21"))
    {
        printf("connect error!\n");
        return 1;
    }
                                                                                                                                                                           
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 220)
    {
        printf("GetFtpReponse 220 error!\n");
        return 1;
    }
    return 0;
}
//登录Ftp服务器
int LoginFtp(tcp_sock& sockCtrl)
{
    char    szRespBuf[RESPONSE_BUF_SIZE + 1];
    //User Name
    if (!SendFtpCmd(sockCtrl, "USER Anonymous"))
    {
        printf("SendFtpCmd error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 331)
    {
        printf("GetFtpReponse 331 error!\n");
        return 1;
    }
    //Pass
    if (!SendFtpCmd(sockCtrl, "PASS asdfa@sina.com"))
    {
        printf("SendFtpCmd error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 230)
    {
        printf("GetFtpReponse 230 error!\n");
        return 1;
    }
    return 0;
}
//上传文件
int UpLoadFile(tcp_sock& sockCtrl, const char* szPath, const char* szFile)
{
    tcp_sock sockData;
    char    szRespBuf[RESPONSE_BUF_SIZE + 1];
    //切换到根目录
    if (!SendFtpCmd(sockCtrl, "CWD /"))
    {
        printf("SendFtpCmd CWD error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 250)
    {
        printf("GetFtpReponse 250 error!\n");
        return 1;
    }
                                                                                                                                                                           
    //调试,显示当前目录
    if (!SendFtpCmd(sockCtrl, "PWD"))
    {
        printf("SendFtpCmd PWD error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 257)
    {
        printf("GetFtpReponse 257 error!\n");
        return 1;
    }
                                                                                                                                                                           
    //设置传送类型为I
    if (!SendFtpCmd(sockCtrl, "TYPE I"))
    {
        printf("SendFtpCmd \"TYPE I\" error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 200)
    {
        printf("GetFtpReponse 200 error!\n");
        return 1;
    }
                                                                                                                                                                               
    //PASV
    if (!SendFtpCmd(sockCtrl, "PASV"))
    {
        printf("SendFtpCmd error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 227)
    {
        printf("GetFtpReponse 227 error!\n");
        return 1;
    }
                                                                                                                                                                           
    char* pPos = strchr(szRespBuf, '(');
    if (pPos == NULL)
    {
        printf("GetFtpReponse Pasv error!\n");
        return 1;
    }
    int ip1, ip2, ip3, ip4, port1, port2;
    if (sscanf(pPos, "(%d,%d,%d,%d,%d,%d)", &ip1, &ip2,
        &ip3, &ip4, &port1, &port2) != 6)
    {
        printf("GetFtpReponse Pasv Address error!\n");
        return 1;
    }
                                                                                                                                                                           
    //生成ip与端口
    char szIP[50];
    char szPort[10];
    sprintf(szIP, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
    sprintf(szPort, "%d", port1*256 + port2);
                                                                                                                                                                           
    //数据链接
    if (!sockData.connect(szIP, szPort))
    {
        printf("Data connect error!\n");
        return 1;
    }
                                                                                                                                                                           
    //STOR
    char szCmdSTOR[100];
    sprintf(szCmdSTOR, "STOR %s", szFile);
    if (!SendFtpCmd(sockCtrl, szCmdSTOR))//发送文件的命令
    {
        printf("SendFtpCmd \"STOR %s\" error!\n",szFile);
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 150)
    {
        printf("GetFtpReponse 150 error!\n");
        return 1;
    }
                                                                                                                                                                               
    //把文件读入缓冲区
    FILE* fp = fopen(szFile, "rb");//必须是rb:二进制打开,只读
    if(fp == NULL)
    {
        printf("Open file %s Error! \n", szFile);
        return 1;
    }
                                                                                                                                                                               
    char szBuf[DATA_BUF_SIZE];
    int nReaded = 0;
    while(1)
    {
        nReaded = fread(szBuf,sizeof(char), DATA_BUF_SIZE, fp);//读入到szBuf,最多读入DATA_BUF_SIZE*sizeof(char)
        //printf("--nReaded:%d\n",nReaded);//测试
        if (nReaded == 0)
            break;
        //szBuf中数据写入套接字缓冲区并发送
        sockData.write(szBuf, nReaded);
        memcpy(szBuf,"\0",DATA_BUF_SIZE);
        //printf("sended\n\n");//测试
    }
    //printf("out\n");//测试
    sockData.close();
    fclose(fp);
    //接收成功吗?
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 226)
    {
        printf("GetFtpReponse 226 error!\n");
        return 1;
    }
    return 0;
}
//退出登陆
int LogoutFtp(tcp_sock& sockCtrl)
{
    char    szRespBuf[RESPONSE_BUF_SIZE + 1];
                                                                                                                                                                           
    //QUIT
    if (!SendFtpCmd(sockCtrl, "QUIT"))
    {
        printf("SendFtpCmd Quit error!\n");
        return 1;
    }
    if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 221)
    {
        printf("GetFtpReponse 221 error!\n");
        return 1;
    }
    return 0;
}
//向ftp服务器发送文件
int FtpPut(const char* szIP, const char* szPath, const char* szFile)
{
    tcp_sock sockCtrl;
    char    szRespBuf[RESPONSE_BUF_SIZE + 1];
                                                                                                                                                                           
    if (ConnectFtp(sockCtrl, szIP) != 0)
        return 1;
    if (LoginFtp(sockCtrl) != 0)
        return 1;
    if (UpLoadFile(sockCtrl, szPath, szFile) != 0)
        return 1;
    LogoutFtp(sockCtrl);
    return 0;
}