一个
ftp
客户端程序,使用了被动模式
#ifndef
__FTP_H__
#define
__FTP_H__
class CFtp
{
public:
CFtp(char *pszServAddr, int nPort);
~CFtp();
public:
int CreateDataSock();
int CreateLocalSocket(char *host, int port);
int Connect();
int Login(char * pszUsername, char * pszPassword);
int Login();
int Logout();
void SendCommand(char * pszCommand);
int GetReply();
int DoAccept(int sd);
int DoReceive(int fd, char szBuffer[], int nLen);
public:
char m_RecvBuff[1024*100];
char m_szRepley[1024*100];
char * DispatchCommand(char *pszCommandType, char *pszCommand);
void ProcessHelp(char *pszCommand);
void ProcessLs(char *pszCommand);
void ProcessGet(char *pszCommand);
private:
char m_szServAddr[25];
int m_nPort;
char m_szUsername[32];
char m_szPassword[32];
int m_Socket;
private:
//
//
int Parse(CAlcatelAdapter * pAdapter);
//
int GetLine(char * buf,char * line,int *islastline);
};
#endif
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftp.h"
CFtp::CFtp(char * pszServAddr, int nPort)
{
strncpy(m_szServAddr, pszServAddr, sizeof(m_szServAddr)-1);
m_nPort = nPort;
}
CFtp::~CFtp()
{
if (m_Socket)
Logout();
}
char * CFtp::DispatchCommand(char *pszCommandType, char *pszCommand)
{
printf("/n/n/n");
memset(m_RecvBuff, 0, sizeof(m_RecvBuff));
if(strcmp(pszCommandType, "HELP") == 0){ //help command
ProcessHelp(pszCommand);
}else if(strcmp(pszCommandType, "RETR") == 0){ //get command
ProcessGet(pszCommand);
}else if(strcmp(pszCommandType, "LIST") == 0){
ProcessLs(pszCommand);
}else{
printf("ERROR command:<%s>", pszCommandType);
}
return m_RecvBuff;
}
void CFtp::ProcessHelp(char *pszCommand)
{
SendCommand(pszCommand);
int ret = GetReply();
sprintf(m_RecvBuff, "%s", m_szRepley);
}
void CFtp::ProcessLs(char *pszCommand)
{
int fd,ret;
fd = CreateDataSock();
if(fd < 0){
printf("ASB>> create listen socket error! /n");
return;
}
SendCommand(pszCommand);
if (GetReply() == -1){
close(fd);
return;
}
sprintf(m_RecvBuff, "%s", m_szRepley);
ret = 1;
int pos = strlen(m_RecvBuff);
while(ret > 0){
ret = DoReceive(fd, m_RecvBuff+pos, sizeof(m_RecvBuff)-pos-1);
}
GetReply();
strcat(m_RecvBuff, m_szRepley);
close(fd);
}
void CFtp::ProcessGet(char *pszCommand)
{
//printf("ASB>> ProcessGet()!");
int ret;
int fd = 0;
char szCommand[256];
char param1[256];
char param2[256];
char param3[256];
char buffer[1024];
//printf("ASB>> pszCommand=%s /n", pszCommand);
sprintf(szCommand, "%s", pszCommand);
sprintf(param1, "%s", strtok(szCommand, " "));
sprintf(param2, "%s", strtok(NULL, " "));
sprintf(param3, "%s", strtok(NULL, " "));
printf("p1=%s, p2=%s, p3=%s /n", param1, param2, param3);
sprintf(szCommand, "%s %s/r/n", param1, param2);
fd = CreateDataSock();
if(fd < 0){
printf("ASB>> create data socket error!");
return;
}
printf("ASB>> create data socket sucess!");
SendCommand(szCommand);
if(GetReply() == -1){
close(fd);
return;
}
FILE *f;
f = fopen(param3, "w+");
for(;;){
memset(buffer, 0, 1024);
ret = recv(fd, buffer, 1024-1, 0);
if (ret > 0){
fwrite(buffer, 1, ret, f);
}else{
break;
}
}
fclose(f);
close(fd);
//
if (GetReply() == -1){
//
printf("ASB>> GetFileReplyCode Error! ReplyCode=%d .",ret);
//
}
}
void CFtp::SendCommand(char * pszCommand)
{
int ret;
ret = send(m_Socket, pszCommand, strlen(pszCommand), 0);
if (ret < 0){
printf("ASB>> >>>>>>>>>>%s error. /n erroninfo:%s /n", pszCommand, strerror(errno));
return;
}else{
printf("ASB>> >>>>>>>>>>%s", pszCommand);
}
}
int CFtp::GetReply()
{
int ret = 1;
int pos = 0;
char szReplyCode[5];
memset(m_szRepley, 0, sizeof(m_szRepley));
while(ret > 0){
ret = DoReceive(m_Socket, m_szRepley+pos, sizeof(m_szRepley)-pos);
if (ret < 0){
printf("ASB>> receive connect reply error. erroninfo:%s /n",strerror(errno));
return -1;
}
pos += ret;
}
//memset(szReplyCode, 0, sizeof(szReplyCode));
//memcpy(szReplyCode, m_RecvBuff, 3);
//ret = atoi(szReplyCode);
return 0;
}
int CFtp::CreateLocalSocket(char *host, int port)
{
struct sockaddr_in addr;
m_Socket = socket(AF_INET,SOCK_STREAM,0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
inet_pton(AF_INET, host, &addr.sin_addr);
addr.sin_port = htons(port);
if( bind(m_Socket, (struct sockaddr*)&addr, sizeof(addr)) < 0){
perror("bind");
return -1;
}
return 0;
}
//连接ftp服务器
int CFtp::Connect()
{
struct sockaddr_in remAddr_in;
int IntOptVaL=1,ret=0,replyCode;
// m_Socket = socket(AF_INET,SOCK_STREAM,0);
// if(m_Socket < 0){
//
printf("ASB>> Fail to open ftp control stream socket. /n");
//
return -1;
// }
setsockopt(m_Socket,SOL_SOCKET,SO_KEEPALIVE,(char*)&IntOptVaL,sizeof(IntOptVaL));
memset((void *)&remAddr_in, 0, sizeof(remAddr_in));
remAddr_in.sin_family = AF_INET;
remAddr_in.sin_port = htons(m_nPort);
remAddr_in.sin_addr.s_addr = inet_addr(m_szServAddr);
if(connect(m_Socket, (struct sockaddr*)&remAddr_in, sizeof(remAddr_in))<0){
printf("ASB>> connect :%s error. erroninfo:%s /n",m_szServAddr,strerror(errno));
close(m_Socket);
m_Socket = 0;
return -1;
}else{
printf("ASB>> Connect to %s successfully. /n", m_szServAddr);
}
replyCode = GetReply();
if(replyCode != 0){
printf("ASB>> Fail to connect. ReplyCode:%d /n", replyCode);
close(m_Socket);
m_Socket = 0;
return -1; /*should close by calling func*/
}
printf("ASB>> **********%s/n", m_szRepley);
return 0;
}
int CFtp::Login(char * pszUsername, char * pszPassword)
{
char szCommand[256];
sprintf(szCommand,"USER %s/r/n", pszUsername);/*send login information:user*/
SendCommand(szCommand);
if (GetReply() == -1){
close(m_Socket);
m_Socket = 0;
return -1; /*should close by calling func*/
}
printf("ASB>> **********%s/n", m_szRepley);
sprintf(szCommand,"PASS %s/r/n", pszPassword);/*send login information:pass*/
SendCommand(szCommand);
if (GetReply() == -1){
close(m_Socket);
m_Socket = 0;
return -1; /*should close by calling func*/
}
printf("ASB>> **********%s/n", m_szRepley);
sprintf(szCommand,"TYPE I/r/n");/*send TYPE command*/
SendCommand(szCommand);
if (GetReply() == -1){
close(m_Socket);
m_Socket = 0;
return -1; /*should close by calling func*/
}
printf("ASB>> **********%s/n", m_szRepley);
return 0;
}
int CFtp::Logout()
{
char szCommand[256];
sprintf(szCommand,"QUIT/r/n");//send QUIT command
SendCommand(szCommand);
if (GetReply() == -1){
close(m_Socket);
m_Socket = 0;
return -1; /*should close by calling func*/
}
return 0;
}
int CFtp::DoAccept(int sd)
{
struct sockaddr_in servaddr;
size_t addlen;
addlen = sizeof(servaddr);
int fd = accept(sd, (struct sockaddr*)&servaddr, &addlen);
if(fd < 0){
return -1;
}
return fd;
}
int CFtp::DoReceive(int fd, char szBuffer[], int nLen)
{
int nOpt = 1;
fd_set rset;
struct timeval tv;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&nOpt, sizeof(nOpt));
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&rset);
FD_SET(fd, &rset);
int ret = select(fd+1, &rset, NULL, NULL, &tv);
if(ret < 0){
if(errno == EINTR) return 0;
return -1;
}else if(ret == 0){
return 0;
}
ret = recv(fd, szBuffer, nLen, 0);
if(ret <= 0){
return -1;
}
return ret;
}
/*
*
Desc: 被动模式下提取需要连接服务端的端口,并由此端口创建socket,接收数据
*/
int CFtp::CreateDataSock()
{
int ret = 0;
int i,j,n,p;
//clear TCP/IP socket data
ret = 1;
while(ret > 0){
ret = DoReceive(m_Socket, m_RecvBuff, sizeof(m_RecvBuff)-1);
}
SendCommand("PASV/r/n");
char szReplyCode[1024];
memset(szReplyCode, 0, 1024);
ret = recv(m_Socket, szReplyCode, 1024, 0);
if (ret < 0){
printf("ASB>> receive connect reply error. erroninfo:%s /n",strerror(errno));
return -1;
}
printf("ASB>> **********%s/n", szReplyCode);
szReplyCode[ret-3]='/0';
char *str1 = szReplyCode+39;
char *str2 = strchr(str1,',');
i = atoi(str2 + 1);
n = 0;
char str3[1024];
memset(str3, 0, 1024);
while(str1[n]!=',')
{
str3[n] = str1[n];
n++;
}
j = atoi(str3);
p = j*256+i;
//create data socket via p(port)
struct sockaddr_in addr;
printf("ASB>> PASV is send,port=%d/n", p);
int datasocket = socket(AF_INET, SOCK_STREAM, 0); //data socket
if (datasocket == -1) return -1;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(p);
addr.sin_addr.s_addr = inet_addr(m_szServAddr);;
ret = connect(datasocket, (struct sockaddr*)&addr, sizeof(addr));
if (ret == -1){
printf("ASB>> datasocket connect %s:%d fail/n", m_szServAddr, p);
return -1;
}
printf("ASB>> datasocket connect %s:%d sucess,datasocket=%d/n", m_szServAddr, p, datasocket);
return datasocket;
}
#if 1
int main(void)
{
CFtp ftp("136.64.1.3", 21);
ftp.Connect();
ftp.Login("sys", "sys");
ftp.DispatchCommand("HELP", "HELP/r/n");
ftp.DispatchCommand("RETR", "RETR test.txt ./test.txt");
ftp.Logout();
}
#endif