头文件
/*! \file PubSleFtp.h
* \version 1.0
* \brief 文件传输功能文件
* \author
* \date 2011-1-11
* \par 修改记录
*/
#ifndef PUB_SLE_FTP_H_
#define PUB_SLE_FTP_H_
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#ifdef __cplusplus
extern "C"
{
#endif
// FTP参数使用,其它模块没有
#define MAX_STRING_LENGTH 1024 //最大字符串长
#define FTP_CHECK_DATA_LENGTH 3 //ftp返回码长
#define ERR_FTP_SEND_USER_INFO_TO_SERVER_FAILED 0xF101 /*向Ftp Server User 账户信息失败*/
#define ERR_FTP_RECV_USER_VALID_RESULT_FAILED 0xF102 /*接收Ftp Server User 验证信息失败*/
#define ERR_FTP_SEND_PWD_TO_SERVER_FAILED 0xF103 /*向Ftp Server Pwd信息失败*/
#define ERR_FTP_RECV_PWD_VALID_RESULT_FAILED 0xF104 /*接收Ftp Server Pwd 验证信息失败*/
#define ERR_FTP_CREATE_SOCKET_FAILED 0xFF01 /*创建Ftp Socket连接失败*/
#define ERR_FTP_CONNECT_TO_SERVER_FAILED 0xFF02 /*连接至FTP Server 失败*/
#define ERR_FTP_INIT_FAILED 0xFF03 /*初始化FTP 失败*/
#define ERR_FTP_ENTER_REMOTE_DIR_SEND_REQ_FAILED 0xFF13 /*切换远程路径失败*/
#define ERR_FTP_ENTER_REMOTE_DIR_SEND_RESP_FAILED 0xFF14 /*切换远程路径失败*/
// FTP文件传输参数结构体
typedef struct _ST_FTP_PARAM
{
char szFtpIp[MAX_STRING_LENGTH]; //ftp服务器ip
char szFtpPort[MAX_STRING_LENGTH]; //ftp服务器端口号
char szFtpUser[MAX_STRING_LENGTH] ; //ftp用户
char szFtpPwd[MAX_STRING_LENGTH] ; //ftp密码
char szLocalPath[MAX_STRING_LENGTH] ; //本地路径
char szRemotePath[MAX_STRING_LENGTH] ; //远程路径
}ST_FtpParam;
/*! \class CPubSleFtp
* \version 1.0
* \brief 文件传输类
* \author
* \date 2009-09-01
* \par 修改记录
*/
class CPubSleFtp
{
public:
/*! \fn CPubSleFtp::CPubSleFtp()
* \brief 构造函数
* \author
* \date 2009-08-03
*/
CPubSleFtp();
/*! \fn CPubSleFtp::~CPubSleFtp()
* \brief 析构函数
* \author
* \date 2009-08-03
*/
virtual ~CPubSleFtp();
public:
/*! \fn int SleInitFtpParam(const ST_FtpParam *pstFtpParam)
* \brief 设置FTP信息
* \param[in] const ST_FtpParam *pstFtpParam ftp参数结构体
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int SleInitFtpParam(const ST_FtpParam *pstFtpParam);
/*! \fn int SleChangeRemoteDir(改变本地和远程目录)
* \param[in] const ST_FtpParam *pstFtpParam ftp参数结构体
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2012-01-05
*/
int SleChangeRemoteDir(const ST_FtpParam *pstFtpParam);
/*! \fn int SleFtpFile(const char *pszFileName, bool bDownMode)
* \brief FTP文件
* \param[in] const char * pszFileName ftp文件名,路径已在 SleInitFtpParam 配置好,此时配置文件名即可
* \param[in] bool bDownMode,ftp传输模式,true:下载;false:上传
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int SleFtpFile(const char *pszFileName, bool bDownMode);
/*! \fn void FtpBye()
* \brief 关闭连接,在Linux下,使用bye作为关闭的shell命令
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
void FtpBye();
private:
/*! \fn int FtpInit()
* \brief ftp初始化
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int FtpInit();
/*! \fn int FtpLogin()
* \brief 登陆FTP服务器
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int FtpLogin();
/*! \fn int EnterRemoteDir()
* \brief 进入远程文件目录
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int EnterRemoteDir();
/*! \fn int DownLoad(const char *pszFileName)
* \brief 下载文件
* \param[in] const char *pszFileName 文件名
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int DownLoad(const char *pszFileName) ;
/*! \fn int UpLoad(const char *pszFileName)
* \brief 上传文件
* \param[in] const char *pszFileName 文件名
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int UpLoad(const char *pszFileName) ;
/*! \fn void DeleteAD(const char *pszStr, int iStrLen, char *pszRetStr)
* \brief 删除回车换行
* \param[in] const char *pszStr 被处理的字符串
* \param[in] int iStrLen 字符串长度
* \param[out] char *pszRetStr 处理后的字符串
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
void DeleteAD(const char *pszStr, int iStrLen, char *pszRetStr);
/*! \fn int GetPort(const char *pszRxBuf)
* \brief 获取传输端口号
* \param[in] const char *pszRxBuf 字符串指针,指向Ftp服务器返回的端口号
* \return int 传输端口号
* \author
* \date 2009-09-01
*/
int GetPort(const char *pszRxBuf);
/*! \fn int WriteFtpData(const char *pszFtpData, int iTxLen)
* \brief 发送FTP数据
* \param[in] const char *pszFtpData 发送数据
* \param[in] int iTxLen 发送数据长度
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int WriteFtpData(const char *pszFtpData, int iTxLen);
/*! \fn int ReadFtpData( int iLength,const char *pszCheckData, char *pszFtpData)
* \brief 读取FTP数据
* \param[in] const char *pszCheckData 返回命令校验码
* \param[in] int iLength 接收数据长度
* \param[out] char *pszFtpData 接收数据
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int ReadFtpData( int iLength,const char *pszCheckData, char *pszFtpData) ;
private:
ST_FtpParam m_stFtpParam; /*ftp参数*/
struct sockaddr_in m_stSockAddr; /*socket addr struct*/
int m_iSocket; /*控制SOCKET*/
int m_iSocketSer; /*传输SOCKET*/
sigset_t m_stOldMask; /*ftp屏蔽信号*/
unsigned int m_randSeed ;
int FtpGetTmpFileName (char * pFileName, char * pTmpFileName) ;
int FtpRename (char * pFromName, char *pToName) ;
int FtpGetSize (const char * pServerFileName);
};
#ifdef __cplusplus
}
#endif/*__cplusplus*/
#endif /*PUB_SLE_FTP_H_*/
源文件
#include "PubSleFtp.h"
#include "PubSleFtpDef.h"
#include "time.h"
#include "stdlib.h"
#include "stdio.h"
#include <netdb.h>
/*! \fn CPubSleFtp::CPubSleFtp()
* \brief 构造函数
* \author
* \date 2009-08-03
*/
bool isIPAddressValid(const char* pszIPAddr) {
if (!pszIPAddr)
return false; //若pszIPAddr为空
char IP1[100], cIP[4];
int len = strlen(pszIPAddr);
int i = 0, j = len - 1;
int k, m = 0, n = 0, num = 0;
//去除首尾空格(取出从i-1到j+1之间的字符):
while (pszIPAddr[i++] == ' ')
;
while (pszIPAddr[j--] == ' ')
;
for (k = i - 1; k <= j + 1; k++) {
IP1[m++] = *(pszIPAddr + k);
}
IP1[m] = '\0';
char *p = IP1;
while (*p != '\0') {
if (*p == ' ' || *p < '0' || *p > '9')
return false;
cIP[n++] = *p; //保存每个子段的第一个字符,用于之后判断该子段是否为0开头
int sum = 0; //sum为每一子段的数值,应在0到255之间
while (*p != '.' && *p != '\0') {
if (*p == ' ' || *p < '0' || *p > '9')
return false;
sum = sum * 10 + *p - 48; //每一子段字符串转化为整数
p++;
}
if (*p == '.') {
if ((*(p - 1) >= '0' && *(p - 1) <= '9')
&& (*(p + 1) >= '0' && *(p + 1) <= '9')) //判断"."前后是否有数字,若无,则为无效IP,如“1.1.127.”
num++; //记录“.”出现的次数,不能大于3
else
return false;
};
if ((sum > 255) || (sum > 0 && cIP[0] == '0') || num > 3)
return false; //若子段的值>255或为0开头的非0子段或“.”的数目>3,则为无效IP
if (*p != '\0')
p++;
n = 0;
}
if (num != 3)
return false;
return true;
}
CPubSleFtp::CPubSleFtp() {
m_iSocket = -1;
m_iSocketSer = -1;
memset(&m_stFtpParam, 0, sizeof(m_stFtpParam));
m_randSeed = time(NULL);
srand(m_randSeed);
}
/*! \fn CPubSleFtp::~CPubSleFtp()
* \brief 析构函数
* \author
* \date 2009-08-03
*/
CPubSleFtp::~CPubSleFtp() {
}
/*! \fn int SleInitFtpParam(const ST_FtpParam *pstFtpParam)
* \brief 设置FTP信息
* \param[in] pstFtpParam ftp参数结构体
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::SleInitFtpParam(const ST_FtpParam *pstFtpParam) {
int iRet = 0xFFFF;
memcpy(&m_stFtpParam, pstFtpParam, sizeof(m_stFtpParam));
iRet = FtpInit();
if (0 != iRet) //ftp初始化
{
return iRet;
}
iRet = FtpLogin();
if (0 != iRet) //ftp登录
{
return iRet;
}
iRet = EnterRemoteDir();
if (0 != iRet) //进入ftp远程目录
{
return iRet;
}
return 0;
}
/*! \fn int SleChangeRemoteDir(改变本地和远程目录)
* \param[in] const ST_FtpParam *pstFtpParam ftp参数结构体
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2011-01-05
*/
int CPubSleFtp::SleChangeRemoteDir(const ST_FtpParam *pstFtpParam) {
int iRet = 0xFFFF;
memcpy(&m_stFtpParam, pstFtpParam, sizeof(m_stFtpParam));
iRet = EnterRemoteDir();
if (0 != iRet) //进入ftp远程目录
{
return iRet;
}
return iRet;
}
/*! \fn int SleFtpFile(const char *pszFileName, bool bDownMode)
* \brief FTP文件
* \param[in] pszFileName ftp文件名
* \param[in] bool bDownMode,ftp传输模式,true:下载;false:上传
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::SleFtpFile(const char *pszFileName, bool bDownMode) {
if (NULL == pszFileName) {
return -1;
}
if (bDownMode) //下载
{
if (0 != DownLoad(pszFileName)) {
return -1;
} else {
}
} else // 上传
{
if (0 != UpLoad(pszFileName)) {
return -1;
} else {
}
}
/*FTP成功返回 */
return 0;
}
/*! \fn int FtpInit()
* \brief ftp初始化
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::FtpInit() {
int iRet = 0;
if (m_iSocket > 0)
close(m_iSocket);
/*< FTP过程中需要屏蔽信号*/
sigset_t newmask;
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
sigaddset(&newmask, SIGPIPE);
sigprocmask(SIG_BLOCK, &newmask, &m_stOldMask);
if ((m_iSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
return ERR_FTP_CREATE_SOCKET_FAILED;
}
memset(&m_stSockAddr, 0x00, sizeof(m_stSockAddr));
m_stSockAddr.sin_family = AF_INET;
char szFtpIp[MAX_STRING_LENGTH] = {0}; //ftp服务器ip
if (isIPAddressValid(m_stFtpParam.szFtpIp))
memcpy(szFtpIp,m_stFtpParam.szFtpIp,strlen(m_stFtpParam.szFtpIp));
else {
int i;
struct hostent *he;
struct in_addr **addr_list;
if ((he = gethostbyname(m_stFtpParam.szFtpIp)) == NULL) { // get the host info
return ERR_FTP_CONNECT_TO_SERVER_FAILED;
}
addr_list = (struct in_addr **) he->h_addr_list;
for (i = 0; addr_list[i] != NULL; i++) {
memcpy(szFtpIp,inet_ntoa(*addr_list[i]),strlen(inet_ntoa(*addr_list[i])));
break;
}
}
m_stSockAddr.sin_addr.s_addr = inet_addr(szFtpIp);
m_stSockAddr.sin_port = htons(atoi(m_stFtpParam.szFtpPort)); /* Port of FTP */
if (-1
== connect(m_iSocket, (struct sockaddr *) &m_stSockAddr,
sizeof(m_stSockAddr))) {
close(m_iSocket);
m_iSocket = -1;
return ERR_FTP_CONNECT_TO_SERVER_FAILED;
}
/* 220-Connect successfully */
//usleep(10000); //服务器应答 “220 x2100-1 FTP server ready.”需要一定的时间延迟
time_t tmStart = time(NULL);
while (time(NULL) <= tmStart + 60) {
char szRxBuf[MAX_STRING_LENGTH];
memset(szRxBuf, 0, sizeof(szRxBuf));
iRet = ReadFtpData(MAX_STRING_LENGTH, (char *) FTP_TRANSMIT_CONNECT,
szRxBuf);
if (0 != iRet) {
usleep(3000);
continue;
}
return 0;
}
return ERR_FTP_INIT_FAILED;
}
/*! \fn int FtpLogin()
* \brief 登陆FTP服务器
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::FtpLogin() {
int iRet = 0xFFFF;
char szBuffer[MAX_STRING_LENGTH];
/*发送用户名*/
char szUser[100];
memset(szBuffer, 0, sizeof(szBuffer));
memset(szUser, 0, sizeof(szUser));
sprintf(szUser, "USER %s\r\n", m_stFtpParam.szFtpUser);
iRet = WriteFtpData(szUser, strlen(szUser));
if (iRet != 0) {
return ERR_FTP_SEND_USER_INFO_TO_SERVER_FAILED;
}
/* 331-User name is ok */
iRet = ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_USER_NAME,
szBuffer);
if (0 != iRet) {
return ERR_FTP_RECV_USER_VALID_RESULT_FAILED;
}
/*发送密码*/
char szPwd[100];
memset(szPwd, 0, sizeof(szPwd));
sprintf(szPwd, "PASS %s\r\n", m_stFtpParam.szFtpPwd);
iRet = WriteFtpData(szPwd, strlen(szPwd));
if (0 != iRet) {
return ERR_FTP_SEND_PWD_TO_SERVER_FAILED;
}
memset(szBuffer, 0, sizeof(szBuffer));
/* 230-Login successfully */
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_PWD,
szBuffer)) {
return ERR_FTP_RECV_PWD_VALID_RESULT_FAILED;
}
/*二进制传输*/
iRet = WriteFtpData((char *) "TYPE I\r\n", 8);
if (0 != iRet) {
return 0xF105;
}
memset(szBuffer, 0, sizeof(szBuffer));
iRet = ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_CHANGE_MODE,
szBuffer);
/* 200-Chang mode successfully */
if (0 != iRet) {
return 0xF106;
}
return 0;
}
/*! \fn int EnterRemoteDir()
* \brief 进入远程文件目录
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::EnterRemoteDir() {
int iRet = 0;
char szBuffer[MAX_STRING_LENGTH];
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "CWD %s\r\n", m_stFtpParam.szRemotePath);
iRet = WriteFtpData(szBuffer, strlen(szBuffer));
if (0 != iRet) {
return ERR_FTP_ENTER_REMOTE_DIR_SEND_REQ_FAILED;
}
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_CWD,
szBuffer)) {
return ERR_FTP_ENTER_REMOTE_DIR_SEND_RESP_FAILED;
}
return 0;
}
/*! \fn int DownLoad(const char *pszFileName)
* \brief 下载文件
* \param[in] pszFileName 文件名
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::DownLoad(const char *pszFileName) {
/*打开本地存放目录*/
DIR *pDir;
char szTemp226Buf[1024] = { 0 };
char *p = NULL;
if ((pDir = opendir(m_stFtpParam.szLocalPath)) == NULL) {
mkdir(m_stFtpParam.szLocalPath, S_IRWXU | S_IRGRP);
}
if (NULL != pDir) {
closedir(pDir);
}
char szBuffer[4 * 1024];
int iFileSize = FtpGetSize(pszFileName); /* Size of file that will be got */
if (iFileSize <= 0)
return -1;
WriteFtpData((char *) "PASV\r\n", 6);
/* 227-Entering passive mode */
memset(szBuffer, 0, sizeof(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_PASSIVE_MODE,
szBuffer)) {
return -2;
}
if ((m_iSocketSer = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return -3;
}
m_stSockAddr.sin_port = GetPort(szBuffer);
if (connect(m_iSocketSer, (const struct sockaddr *) &m_stSockAddr,
sizeof(m_stSockAddr))) {
close(m_iSocketSer);
return -4;
}
// printf ("Connect Data Socket [%d]\n" , m_iSocketSer) ;
/*创建文件*/
FILE *pfRecvFile = NULL; /* Receive file */
sprintf(szBuffer, "%s/%s", m_stFtpParam.szLocalPath, pszFileName);
if ((pfRecvFile = fopen(szBuffer, "wb")) == NULL) {
close(m_iSocketSer);
return -5; /* Open file to receive fail */
}
sprintf(szBuffer, "RETR %s/%s\r\n", m_stFtpParam.szRemotePath, pszFileName);
WriteFtpData(szBuffer, strlen(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_RETR,
szBuffer)) {
fclose(pfRecvFile);
close(m_iSocketSer);
return -6;
}
memset(szTemp226Buf, 0, sizeof(szTemp226Buf));
sprintf(szTemp226Buf, "%s", szBuffer);
int iTransFileSize = 0;
int iLength = 0; /* Length of data that be sent */
int iSelectTimeout = 120;
struct timeval stTimeOut;
int iErrorCount = 0;
while (true)
{
stTimeOut.tv_sec = iSelectTimeout;
stTimeOut.tv_usec = 0;
fd_set stReadReady;
FD_ZERO(&stReadReady);
FD_SET(m_iSocketSer, &stReadReady);
int iRet = 0;
iRet = select(m_iSocketSer + 1, &stReadReady, NULL, NULL, &stTimeOut);
if (iRet == 0) {
if (iErrorCount < 2) {
iErrorCount++;
usleep(3000);
continue;
}
// timeout or Error.
break;
// continue ;
}
if (iRet < 0) {
// Error Occurs
if ((errno == EINTR || errno == EAGAIN) && iErrorCount < 2) {
iErrorCount++;
usleep(3000);
continue;
} else
break;
}
if (FD_ISSET(m_iSocketSer, &stReadReady) == false) {
break;
}
// Read Bytes
iLength = recv(m_iSocketSer, szBuffer, sizeof(szBuffer), MSG_DONTWAIT);
if (iLength <= 0) {
printf("[%s][%d] recv Error = [%d], [%s]\n", __FUNCTION__, __LINE__,
errno, strerror(errno));
if (errno == EINTR || errno == EAGAIN) {
sleep(1);
continue;
}
break;
}
fwrite(szBuffer, iLength, 1, pfRecvFile);
iTransFileSize += iLength;
if (iTransFileSize >= iFileSize)
break;
}
printf("[%s][%d] iTransFileSize = [%d], iFileSize = [%d]\n", __FUNCTION__,
__LINE__, iTransFileSize, iFileSize);
if (iTransFileSize != iFileSize) {
close(m_iSocketSer);
fclose(pfRecvFile);
return -7; /*文件未传输完 */
}
close(m_iSocketSer);
fclose(pfRecvFile);
/* 226-End of sending data */
memset(szBuffer, 0, sizeof(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_END,
szBuffer)) {
//add by at 20120809: 为了解决Ftp下载失败的问题
p = strstr(szTemp226Buf, "226");
if (p == NULL)
return -8;
else
printf(
"\n Warning: has receive 226 at the same time for receive 150 \n");
}
return 0; //下载成功
}
/*! \fn int UpLoad(const char *pszFileName)
* \brief 上传文件
* \param[in] pszFileName 文件名
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::UpLoad(const char *pszFileName) {
char szTemp226Buf[1024] = { 0 };
char *p = NULL;
/* 227-Entering passive mode */
WriteFtpData((char *) "PASV\r\n", 6);
char szBuffer[MAX_STRING_LENGTH];
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_PASSIVE_MODE,
szBuffer)) {
return -1;
}
if ((m_iSocketSer = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("[%s][%d]Create socket for data transfer err[%d]!\n", __FILE__,
__LINE__, errno);
return -2;
}
m_stSockAddr.sin_port = GetPort(szBuffer);
if (connect(m_iSocketSer, (const struct sockaddr *) &m_stSockAddr,
sizeof(m_stSockAddr)) == -1) {
printf("[%s][%d]Connect to transfer port(%d) err[%d]!\n",
__FILE__, __LINE__, ntohs(m_stSockAddr.sin_port), errno);
close(m_iSocketSer);
return -3;
}
/*打开本地文件*/
FILE *pfSendFile = NULL;
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "%s", pszFileName);
if ((pfSendFile = fopen(szBuffer, "rb")) == NULL) {
printf("[%s][%d]open local file[%s] err\n", __FILE__, __LINE__,
szBuffer);
close(m_iSocketSer);
return -4;
}
char *pFileName = NULL;
pFileName = strrchr((char*) pszFileName, '/');
pFileName += 1; // Skip dir /.
char pTmpFileName[1024];
memset(pTmpFileName, 0, sizeof(pTmpFileName));
FtpGetTmpFileName(pFileName, pTmpFileName);
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "STOR ./%s\r\n", pTmpFileName);
WriteFtpData(szBuffer, strlen(szBuffer));
/* 150-Opening data connection */
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_RETR,
szBuffer)) {
fclose(pfSendFile);
close(m_iSocketSer);
return -5;
}
printf("\n the content of buffer after receive 150 : %s \n", szBuffer);
memset(szTemp226Buf, 0, sizeof(szTemp226Buf));
sprintf(szTemp226Buf, "%s", szBuffer);
/*确定文件大小,传输文件*/
int iLength = 0;
struct stat buf;
stat(pszFileName, &buf);
int iFileSize = buf.st_size;
int len, n;
int iSendFileSize = 0;
while (!feof(pfSendFile)) {
iLength = fread(szBuffer, 1, MAX_STRING_LENGTH, pfSendFile);
len = 0;
n = 0;
while (iLength != len) {
n = send(m_iSocketSer, (szBuffer + len), (iLength - len), 0);
if (n < 0)
break;
len += n;
}
if (n < 0)
break;
iSendFileSize += iLength;
if (iSendFileSize > iFileSize)
break;
}
if (iSendFileSize < iFileSize) {
printf("[%s][%d]sendfile size[%d] < filesize[%d]\n", __FILE__, __LINE__,
iSendFileSize, iFileSize);
fclose(pfSendFile);
close(m_iSocketSer);
return -6;
}
fclose(pfSendFile);
close(m_iSocketSer);
/* 226-Transfer complete */
memset(szBuffer, 0, sizeof(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_END,
szBuffer)) {
p = strstr(szTemp226Buf, "226");
if (p == NULL)
return -7;
else
printf(
"\n Warning: has receive 226 at the same time for receive 150 \n");
}
// Get Size of Server File .
iSendFileSize = FtpGetSize(pTmpFileName);
if (iSendFileSize != iFileSize) {
// File Size Error.
return -8;
}
// Try to Rename File .
iSendFileSize = FtpRename(pTmpFileName, pFileName);
return iSendFileSize;
// return 0; /* UpLoad Succuss */
}
/*! \fn void FtpBye()
* \brief 关闭连接
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
void CPubSleFtp::FtpBye() {
char szBuffer[MAX_STRING_LENGTH];
memset(szBuffer, 0, sizeof(szBuffer));
if (m_iSocket > 0) //add by at 20140210
{
WriteFtpData((char *) "QUIT\r\n", 6);
ReadFtpData(MAX_STRING_LENGTH, (char *) FTP_TRANSMIT_BYE, szBuffer); /* 221-Disconnect successfully */
close(m_iSocket);
}
sigprocmask(SIG_SETMASK, &m_stOldMask, NULL);
m_iSocket = -1;
}
/*! \fn void DeleteAD(const char *pszStr, int iStrLen, char *pszRetStr)
* \brief 删除回车换行
* \param[in] pszStr 被处理的字符串
* \param[in] iStrLen 字符串长度
* \param[out] pszRetStr 处理后的字符串
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
void CPubSleFtp::DeleteAD(const char *pszStr, int iStrLen, char *pszRetStr) {
assert(pszStr);
assert(pszRetStr);
char *pszStrA, *pszStrD;
memcpy(pszRetStr, pszStr, iStrLen);
pszStrA = (char*) strchr(pszRetStr, 0x0A);
pszStrD = (char*) strchr(pszRetStr, 0x0D);
if ((NULL != pszStrA) && (NULL != pszStrD)) {
(pszStrA < pszStrD) ? (*pszStrA = 0x00) : (*pszStrD = 0x00);
} else {
if (NULL != pszStrA) {
*pszStrA = 0x00;
}
if (pszStrD) {
*pszStrD = 0x00;
}
}
}
/*! \fn int GetPort(const char *pszRxBuf)
* \brief 获取传输端口号
* \param[in] const char *pszRxBuf 字符串指针,Ftp服务器返回的端口号
* \param[out] 无
* \return int 传输端口号
* \author
* \date 2009-09-01
*/
int CPubSleFtp::GetPort(const char *pszRxBuf) {
char *Lo, *Hi, *End;
int iPort = 0;
;
End = (char*) strrchr(pszRxBuf, ')');
*End = 0x00;
Lo = (char*) strrchr(pszRxBuf, ',');
*Lo = 0x00;
Hi = (char*) strrchr(pszRxBuf, ',');
iPort = atoi(Hi + 1) * 256 + atoi(Lo + 1);
return (htons(iPort));
}
/*! \fn int WriteFtpData(const char *pszFtpData, int iTxLen)
* \brief 发送FTP数据
* \param[in] const char *pszFtpData 发送数据
* \param[in] int iTxLen 发送数据长度
* \param[out] 无
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::WriteFtpData(const char *pszFtpData, int iTxLen) {
assert(pszFtpData);
if (send(m_iSocket, pszFtpData, iTxLen, 0) < iTxLen) {
close(m_iSocket);
m_iSocket = -1;
return 0xFF06;
}
return 0;
}
/*! \fn int ReadFtpData( int iLength,const char *pszCheckData, char *pszFtpData)
* \brief 读取FTP数据
* \param[in] const char *pszCheckData 返回命令校验码
* \param[in] int iLength 接收数据长度
* \param[out] char *pszFtpData 接收数据
* \return int 0 成功, -1 失败
* \author
* \date 2009-09-01
*/
int CPubSleFtp::ReadFtpData(int iLength, const char *pszCheckData,
char *pszFtpData) {
struct timeval stTimeOut;
stTimeOut.tv_sec = 30;
stTimeOut.tv_usec = 0;
int iReadLen = 0;
time_t tmStartTime = time(NULL);
while (time(NULL) <= tmStartTime + stTimeOut.tv_sec) {
if (m_iSocket <= 0) {
printf("m_iSocket [%d] Failed. \n", m_iSocket);
return 0xFFFE;
}
fd_set stReadReady;
FD_ZERO(&stReadReady);
FD_SET(m_iSocket, &stReadReady);
if (select(m_iSocket + 1, &stReadReady, NULL, NULL, &stTimeOut) <= 0) {
printf("Select Read Failed. \n");
if (errno == EAGAIN || errno == EINTR) {
usleep(3000);
continue;
} else
break;
}
if (FD_ISSET(m_iSocket, &stReadReady) == false) {
printf("FD_ISSET == false. \n");
if (errno == EAGAIN || errno == EINTR) {
usleep(3000);
continue;
} else
break;
}
// Read 1 Bytes
int iLen = recv(m_iSocket, pszFtpData + iReadLen,
1 /*iLength-iReadLen*/, 0);
if (iLen <= 0) {
printf("recv Failed iLen = [%d]. \n", iLen);
if (errno == EAGAIN || errno == EINTR) {
usleep(3000);
continue;
} else
return -1;
}
if (*(pszFtpData + iReadLen) == '\n') // \r\n
{
*(pszFtpData + iReadLen + 1) = '\0';
iReadLen += 1;
break;
}
iReadLen += iLen;
stTimeOut.tv_sec = 40;
}
if (iReadLen <= 0)
return -2;
if (memcmp(pszFtpData, pszCheckData, FTP_CHECK_DATA_LENGTH) == 0) {
return 0;
} else {
pszFtpData[3] = '\0';
// return Error Code.
return -3;
}
}
int CPubSleFtp::FtpGetSize(const char * pServerFileName) {
char szBuffer[MAX_STRING_LENGTH];
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "SIZE %s\r\n", pServerFileName);
WriteFtpData(szBuffer, strlen(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer), (char *) FTP_TRANSMIT_FILE_SIZE,
szBuffer)) {
return -1;
}
/*确定文件大小*/
char szTempBuf[MAX_STRING_LENGTH];
memset(szTempBuf, 0, sizeof(szTempBuf));
DeleteAD(szBuffer, strlen(szBuffer), szTempBuf);
int iFileSize = atoi(szTempBuf + 4); /* Size of file that will be got */
return iFileSize;
}
int CPubSleFtp::FtpRename(char * pFromName, char *pToName) {
// Send RNFR
char szBuffer[MAX_STRING_LENGTH];
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "RNFR %s\r\n", pFromName);
WriteFtpData(szBuffer, strlen(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer),
(char *) FTP_TRANSMIT_PENDING_FOR_MORE_INFO, szBuffer)) {
return -1;
}
// Send RNTO
memset(szBuffer, 0, sizeof(szBuffer));
sprintf(szBuffer, "RNTO %s\r\n", pToName);
WriteFtpData(szBuffer, strlen(szBuffer));
if (0
!= ReadFtpData(sizeof(szBuffer),
(char *) FTP_TRANSMIT_FILE_ACTION_OK, szBuffer)) {
return -1;
}
return 0;
}
int CPubSleFtp::FtpGetTmpFileName(char * pFileName, char * pTmpFileName) {
sprintf(pTmpFileName, "%s.tmp%03d", pFileName,
rand(/*&m_randSeed*/) % 1000);
return 0;
}
定义头文件
#ifndef PUBSLEFTPDEF_H_
#define PUBSLEFTPDEF_H_
#include <sys/types.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <link.h>
#include <time.h>
#include <dirent.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
//ftp命令返回码,标准的FTP协议
#define FTP_TRANSMIT_CONNECT "220"
#define FTP_TRANSMIT_BYE "221"
#define FTP_TRANSMIT_USER_NAME "331"
#define FTP_TRANSMIT_PWD "230"
#define FTP_TRANSMIT_CHANGE_MODE "200"
#define FTP_TRANSMIT_CWD "250"
#define FTP_TRANSMIT_FILE_SIZE "213"
#define FTP_TRANSMIT_PASSIVE_MODE "227"
#define FTP_TRANSMIT_RETR "150"
#define FTP_TRANSMIT_END "226"
#define FTP_TRANSMIT_PENDING_FOR_MORE_INFO "350"
#define FTP_TRANSMIT_FILE_ACTION_OK "250"
#endif /*PUBSLEFTPDEF_H_*/