📄 tftpclient.cpp
字号:
#include "TFTPClient.h"
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#ifndef INADDR_NONE
#define INADDR_NONE (in_addr_t)0xffffffff
#endif
TFTPClient::TFTPClient()
{
/* 默认超时设为60秒 */
m_iTimeOut=(OPTVAL)60;
m_iMaxWaitTime = (OPTVAL)60;
/* 默认为不支持断点续传 */
m_iResume=NO;
/* 获取主机字节序 */
m_IsBigOrder=IsBigOrder();
}
/********************************************************
* function:FTPOption
* purpose:设置ftp选项
* return:
*********************************************************/
int TFTPClient::FTPOption(FTPOPTION option, OPTVAL value){
switch(option){
/*超时设置*/
case TIMEOUT:
m_iTimeOut = value;
break;
case MAXWAITTIME:
m_iMaxWaitTime = value;
break;
/*文件传输数据类型设置*/
case DATATYPE:
/* 设置传输数据类型 */
if( value == BINARY )
return FTPCommand("TYPE I\r\n");
else if( value == ASCII )
return FTPCommand("TYPE A\r\n");
else {
printf(" DATATYPE does not exist\n");
return -1;
}
/*断点续传设置*/
case RESUME:
m_iResume=value;
break;
default:
printf(" option does not exist\n");
return -1;
}
return 0;
}
TFTPClient::~TFTPClient()
{
}
/********************************************************
* function:FTPLogIn
* purpose:登录到FTP Server
* return: FTP_SUCCEED 成功 , FTP_FAIL 失败
*
*********************************************************/
int TFTPClient::FTPLogin(const char *strServer, const char *strUser, const char *strPassword)
{
struct hostent *lpHostEnt; /* Internet host information structure*/
struct sockaddr_in sockAddr; /* Socket address structure */
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(21);
if (inet_pton(AF_INET, strServer, &sockAddr.sin_addr) <= 0)
{
if (!(lpHostEnt = gethostbyname(strServer))){
perror("gethostbyname inet_pton error!");
return -1;
}
sockAddr.sin_addr = *((struct in_addr *)*lpHostEnt->h_addr_list);
}
if ((m_hControlChannel = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket() create ");
return -1;
}
time_t ttTmp = time(NULL);
if(connect(m_hControlChannel, reinterpret_cast<struct sockaddr *>(&sockAddr), sizeof(sockAddr)) < 0){
close(m_hControlChannel);
perror("connect()");
if(time(NULL) - ttTmp < 5 ) return -11;
else return FTP_E_CONNECT;
}
int ret= WaitResult(m_hControlChannel);
if(ret != 220){
close(m_hControlChannel);
return -11;
}
/* 发送user命令 */
char buf[256];
snprintf(buf, sizeof(buf), (char*)"USER %s\r\n",strUser);
int len=strlen(buf);
ret = Write(m_hControlChannel, buf, &len);
if( ret < 0 || len != strlen(buf) ){
close(m_hControlChannel);
return FTP_E_CONNECT;
}
ret = WaitResult(m_hControlChannel);
if(ret != 331){
close(m_hControlChannel);
return FTP_E_USER;
}
/*发送pass命令*/
snprintf(buf, sizeof(buf), (char*)"PASS %s\r\n", strPassword);
len = strlen(buf);
ret = Write(m_hControlChannel,buf,&len);
if( ret < 0 || len != strlen(buf) ) {
close(m_hControlChannel);
return FTP_E_CONNECT;
}
ret = WaitResult(m_hControlChannel);
if(ret != 230){
close(m_hControlChannel);
return FTP_E_PASS;
}
return 0;
}
/********************************************************
* function:CreateListenSocket
* purpose:create listen socket (let it choose the port) & start the socket listening
* return: FTP_SUCCEED 成功 , FTP_FAIL 失败
*
********************************************************/
int TFTPClient::CreateListenSocket()
{
struct sockaddr_in sockAddr;
/* 分配套接口 */
if ((m_hListenSocket = socket( AF_INET, SOCK_STREAM, 0 ))<0){
perror("socket()");
return -1;
}
/* Let the system assign a socket address */
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(0); /* htons() is just a reminder.*/
sockAddr.sin_addr.s_addr = INADDR_ANY;
/* Bind the socket */
if (bind(m_hListenSocket, reinterpret_cast<struct sockaddr *>(&sockAddr), sizeof(sockAddr))){
close(m_hListenSocket);
perror("bind()");
return -1;
}
int tmpint = fcntl(m_hListenSocket, F_GETFL, 0);
if (fcntl(m_hListenSocket, F_SETFL, tmpint|O_NONBLOCK) < 0){
close(m_hListenSocket);
perror("fcntl");
return -1;
}
/* Listen for the FTP server connection */
if (listen(m_hListenSocket, 3)){
close(m_hListenSocket);
perror("listen()");
return -1;
}
/* Ask the server to connect to the port monitored by the listener socket*/
#if defined(_AIX) || defined(__linux__)
socklen_t iLength = sizeof(sockAddr);
#else
int iLength = sizeof(sockAddr);
#endif
/* 发送PORT命令 */
/* Get port number */
if(getsockname(m_hListenSocket, reinterpret_cast<struct sockaddr *>(&sockAddr), &iLength) <0){
close(m_hListenSocket);
printf("getsockname");
return -1;
}
int iPort=sockAddr.sin_port;
/* Get local ip address */
if(getsockname(m_hControlChannel, reinterpret_cast<struct sockaddr *>(&sockAddr), &iLength) <0){
close(m_hListenSocket);
printf("getsockname");
return -1;
}
char strCmd[128];
//PORT h1,h2,h3,h4,p1,p2
//where h1 is the high order 8 bits of the internet host address.
if(m_IsBigOrder == 1)
sprintf(strCmd, "PORT %d,%d,%d,%d,%d,%d\r\n",
(sockAddr.sin_addr.s_addr>>24) & 0x000000ff,
(sockAddr.sin_addr.s_addr>>16) & 0x000000ff,
(sockAddr.sin_addr.s_addr>>8) & 0x000000ff,
(sockAddr.sin_addr.s_addr) & 0x000000ff,
iPort >> 8,
iPort & 0xFF);
else
sprintf(strCmd, "PORT %d,%d,%d,%d,%d,%d\r\n",
(sockAddr.sin_addr.s_addr) & 0x000000ff,
(sockAddr.sin_addr.s_addr>>8) & 0x000000ff,
(sockAddr.sin_addr.s_addr>>16) & 0x000000ff,
(sockAddr.sin_addr.s_addr>>24) & 0x000000ff,
iPort & 0xFF,
iPort >>8 );
int len=strlen(strCmd);
int ret = Write(m_hControlChannel,strCmd,&len);
if( ret < 0 || len != strlen(strCmd) ){
close(m_hListenSocket);
return -1;
}
/* here we should get the result: 200 PORT command successful. */
ret = WaitResult(m_hControlChannel);
if(ret != 200){
close(m_hListenSocket);
return -1;
}
return 0;
}
/*
*get a file from remote ftp server
*return 0 -- get successfully
*return -1 -- some error !
*return -5 -- remote file doesn't exist
*/
int TFTPClient::GetFile(const char* strRemote, const char* strLocal )
{
if( CreateListenSocket() < 0 )
return -1;
const char* cpLocalFile = (strLocal == NULL ? strRemote : strLocal);
char buf[10240];
if( m_iResume == YES ) {
struct stat filestat;
if(stat(cpLocalFile, &filestat) < 0){
filestat.st_size = 0;
}
snprintf(buf, sizeof(buf), (char*)"REST %d\r\n", filestat.st_size);
int len = strlen(buf);
int ret = Write(m_hControlChannel,buf,&len);
if( ret < 0 || len != strlen(buf) ){
close(m_hListenSocket);
return -2;
}
// 如果服务器支持断点续传,那么返回应答应是:
// 350 Restarting at 0. Send STORE or RETRIEVE to initiate transfer.
ret = WaitResult(m_hControlChannel);
if( ret < 0 ) {
close(m_hListenSocket);
return -3;
}
if( ret/100 != 3 ) {
m_iResume = NO;
printf("FTP server does not support rest command\n");
}
}
snprintf(buf, sizeof(buf), (char*)"RETR %s\r\n", strRemote);
int len = strlen(buf);
int ret = Write(m_hControlChannel, buf, &len);
if( ret < 0 || len != strlen(buf) ){
close(m_hListenSocket);
return -4;
}
ret = Accept(m_hListenSocket, NULL, NULL);
close(m_hListenSocket);
if(ret > 0 ){
m_hDataSocket=ret;
}
else {
ret = WaitResult(m_hControlChannel);
if(ret == 550 ) return -5 ;
return -6;
}
ret = WaitResult(m_hControlChannel);
if(ret != 150){
close(m_hDataSocket);
return -7;
}
int fd;
if((fd = open( cpLocalFile, m_iResume == YES ? O_CREAT|O_APPEND|O_RDWR : O_CREAT|O_TRUNC|O_RDWR, 0660)) < 0 ){
close( m_hDataSocket) ;
perror("open file");
return -8;
}
int timer = time(0);
int totallen = 0;
int tmptime;
while(1){
tmptime = time(0);
if( tmptime >= timer + m_iMaxWaitTime ){
close(m_hDataSocket);
printf("time out %d seconds when get a remote file\n", m_iMaxWaitTime);
close(fd);
return -9;
}
len = 10240;
ret = Read(m_hDataSocket, buf, &len);
if(ret != 0 )
break;
else if( len == 0 )
continue;
timer = tmptime;
if( write( fd, buf, len) < len) {
perror("write file");
close(fd);
close(m_hDataSocket);
return -10;
}
totallen += len;
}
close(fd);
close(m_hDataSocket);
ret = WaitResult(m_hControlChannel);
if( ret == 226 ) return 0 ;
return -11;
}
/*
*put a file to remote ftp server
*return 0 -- put successfully
*return -1 -- some error !
*return -3 -- file doesn't exist
*/
int TFTPClient::PutFile(const char* strLocal, const char* strRemote)
{
if( CreateListenSocket() < 0 )
return -1;
struct stat filestat;
const char* cpRemoteFile = (strRemote == NULL ? strLocal : strRemote);
char buf[10240];
sprintf( buf, "STOR %s\r\n", cpRemoteFile);
int len = strlen(buf);
int ret = Write(m_hControlChannel,buf,&len);
if( ret < 0 || len != strlen(buf) ) {
close(m_hListenSocket);
return -2;
}
ret=Accept(m_hListenSocket,NULL,NULL);
close(m_hListenSocket);
if(ret > 0 )
m_hDataSocket=ret;
else {
ret = WaitResult(m_hControlChannel);
if( ret == 550 ) return -3 ;
return -4;
}
ret = WaitResult(m_hControlChannel);
if(ret != 150){
close(m_hDataSocket);
return -5;
}
int fd;
if((fd = open(strLocal, O_RDONLY, 0660)) < 0) {
close(m_hDataSocket);
perror("open file");
return -6;
}
if( fstat(fd, &filestat) < 0) {
printf("File:%s stat error!\n",strLocal);
close(m_hDataSocket);
close(fd);
return -7;
}
int totallen = filestat.st_size;
int timer = time(0);
ret = 0;
int tmplen,tmptime;
while(totallen > 0) {
tmptime = time(0);
if(tmptime >= timer + m_iMaxWaitTime ){
printf("time out %d seconds in putfile\n", m_iMaxWaitTime);
ret = -1;
break;
}
if(totallen < 256)
len = totallen;
else
len = 256;
ret=read( fd, buf, len);
if(ret<=0)
break;
else
tmplen = len = ret;
ret=Write(m_hDataSocket,buf,&tmplen);
if( ret < 0 || tmplen != len ){
close(fd);
close(m_hDataSocket);
return -8;
}
timer = tmptime;
totallen -= len;
}
close(fd);
close(m_hDataSocket);
ret=WaitResult(m_hControlChannel);
if( ret != 226 ) return -9;
return 0;
}
/********************************************************
* function:FTPCmd
* purpose:执行ftp服务器端命令
* return: FTP_SUCCEED 成功 , FTP_FAIL 失败
*CHDIR, CDUP, DEL, LS, PWD, MKDIR, RMDIR,SYSTYPE
*********************************************************/
int TFTPClient::FTPCmd(FTPCMDTYPE cmd, const char* cmdvalue, char* returnvalue, int retmaxsize)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -