linux FTP系统编程 应用编程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/fengweibo112/article/details/99682415

概述

根本例实现从FTP server下载一个文件到本地,据需要,修改如下的宏定义则可运行。
#define FTP_USER_NAME “user” //FTP Server的用户名
#define FTP_USER_PSW “123456”//FTP Server的密码
#define FTP_IP “10.124.1.20” //FTP Server的IP
#define FTP_COMMAND_PORT 21 //端口号一般是21,不用修改
#define DWN_FILE_PATH “/test.c” //下载文件在FTP server的路径
#define SAVE_FILE_PATH “/home/user/test.c” //保存文件路径

源代码

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define FTP_USER_NAME "user"
#define FTP_USER_PSW  "123456"
#define FTP_IP        "10.124.1.20"
#define FTP_COMMAND_PORT      21
#define DWN_FILE_PATH   "/test.c"
#define SAVE_FILE_PATH   "/home/user/test.c"

/**********************************
*功能:TCP连接到指定IP和端口
*返回:-1 连接失败; 其它:文件描述符
*说明:
***********************************/
int tcp_sockConnect(char *ip,int port)
{
 int sockfd;
 struct sockaddr_in server_add;
 
 memset(&server_add, 0, sizeof(struct sockaddr_in));
 
 /*初始化socket*/
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 if(sockfd == -1)
 {
  printf("create socket err\r\n");
  return -1;
 }
 server_add.sin_family        = AF_INET;    /* IP protocol family.example:IPV4\IPV6*/
 server_add.sin_port          = htons(port);  /* Port number*/
 server_add.sin_addr.s_addr   = inet_addr(ip); /* Internet address AF_INET*/
 
 /*连接到服务器*/
 if(connect(sockfd, (struct sockaddr *)&server_add, sizeof(server_add)) == -1)
 {
  printf("socket connect err\r\n");
  return -1;
 }
 return sockfd;
}

/**********************************
*功能:FTP命令端口套字节连接,命令端口一般是21
*返回:-1 连接失败; 其它:文件描述符
*说明:
***********************************/
int ftp_commandSocketConnect(char *ip,int port)
{
char rcvBuf[512];  
 int commandSock;
 int res;
 
 /*TCP连接到命令端口*/
 commandSock = tcp_sockConnect(ip,port);
 if(res == -1)
 {
  printf("ftp command socket connect err\r\n");
  return -1;
 }
 
 /*从服务端接收欢迎信息*/
 if(recv(commandSock,rcvBuf,512,0) == -1)
 {
  printf("ftp receive welcome message err\r\n");
  return -1;
 }
 sscanf(rcvBuf,"%d",&res);/*正常返回220响应码*/
 if(res != 220)
 {
  printf("ftp welcome result err !=220\r\n");
  close(commandSock);
  return -1;
 }
 
 return commandSock;
}

/**********************************
*功能:客户端发送用户名和密码,登陆FTP服务器
*返回:-1 登陆失败;0 登陆成功
*说明:
***********************************/
int ftp_loginServer(int commandSock,char *userName,char *passWord)
{
char sendBuf[100];
 char rcvBuf[100];
 int res;
 
 /*命令 "USER username\r\n"*/
 sprintf(sendBuf,"USER %s\r\n",userName);
 
 /*客户端发送用户名到服务器端 */
 if(send(commandSock,sendBuf,strlen(sendBuf),0) == -1)
 {
  printf("ftp socket send err\r\n");
  return -1;
 }
 
 /* 客户端接收服务器的响应码和信息,正常为 ”331 User name okay, need password.” */
 if(recv(commandSock,rcvBuf,100,0) == -1)
 {
  printf("ftp recv login user message err\r\n");
  return -1;
 }
 sscanf(rcvBuf,"%d",&res);
 if(res != 331)
 {
  printf("ftp user command result err !=331\r\n");
  return -1;
 }
 
 /*命令 "PASS password\r\n"*/
 sprintf(sendBuf,"PASS %s\r\n",passWord);
 /* 客户端发送密码到服务器端 */ 
 if(send(commandSock,sendBuf,strlen(sendBuf),0) == -1)
 {
  printf("ftp socket send err");
  return -1;
 }
 /* 客户端接收服务器的响应码和信息,正常为 ”230 User logged in, proceed.” */
 if(recv(commandSock,rcvBuf,100,0) == -1)
 {
  printf("ftp recv login password message err\r\n");
  return -1;
 }
 sscanf(rcvBuf,"%d",&res);
 if(res != 230)
 {
  printf("ftp PASS command result err !=230\r\n");
  return -1;
 }
 
 return 0;
}
/**********************************
*功能:被动模式下,接收FTP服务器返回的数据端口号,并TCP连接到数据端口
*返回:-1 连接数据端口失败,其它 返回数据端口的文件描述符
*参数:commandSock 命令sock描述符
*说明:
***********************************/
int ftp_dataSocketConnect(int commandSock)
{
char sendBuf[100];
 char rcvBuf[100];
 int  dataSock;
 int  rcvAddBuf[6];/*接收到的IP和端口数据*/
 char addStr[20];/*IP地址字符串格式*/
 int res;
 
 /*命令 "PASV\r\n"*/
 sprintf(sendBuf,"PASV\r\n");
 /* 客户端发送密码到服务器端 */ 
 if(send(commandSock,sendBuf,strlen(sendBuf),0) == -1)
 {
  printf("ftp socket send err\r\n");
  return -1;
 }
 
 /*客户端接收服务器的响应码和新开的端口号, * 
 正常为 ”227 Entering passive mode (<h1,h2,h3,h4,p1,p2>)” */
 if(recv(commandSock,rcvBuf,100,0) == -1)
 {
  printf("ftp recv login password message err\r\n");
  return -1;
 }
 sscanf(rcvBuf,"%d",&res);
 if(res != 227)
 {
  printf("ftp PASV command result err !=227\r\n");
  return -1;
 }
 /*从返回的消息中提取数据通道的IP和Port*/
 sscanf(rcvBuf,"%*[^(](%d,%d,%d,%d,%d,%d)",&rcvAddBuf[0],&rcvAddBuf[1],&rcvAddBuf[2]\
   ,&rcvAddBuf[3],&rcvAddBuf[4],&rcvAddBuf[5]);
 sprintf(addStr,"%d.%d.%d.%d",rcvAddBuf[0],rcvAddBuf[1],rcvAddBuf[2],rcvAddBuf[3]);
 
 /*连接到数据端口*/
 dataSock = tcp_sockConnect(addStr,rcvAddBuf[4]*256+rcvAddBuf[5]);
 if(dataSock == -1)
 {
  printf("ftp connect data prot err\r\n");
  return -1;
 }
 
 return dataSock;
}

/**********************************
*功能:从FTP服务器下载文件
*返回:
*参数:
*说明:
***********************************/
int ftp_downloadFile(int commandSock,int dataSock,char *downPath,char *savePath)
{
 char sendBuf[100];
 char rcvBuf[100];
 int  rcvLength;
 FILE *fp = NULL;
 int res;
 
 /* 命令 ”RETR filename\r\n” */
 sprintf(sendBuf,"RETR %s\r\n",downPath);
 /* 客户端发送下载命令到服务器端 */ 
 if(send(commandSock,sendBuf,strlen(sendBuf),0) == -1)
 {
  printf("ftp socket send err\r\n");
  return -1;
 }
 
 /* 客户端接收服务器的响应码和信息,正常为 ”150 Opening data connection.” */ 
 if(recv(commandSock,rcvBuf,100,0) == -1)
 {
  printf("ftp recv login password message err\r\n");
  return -1;
 }
 sscanf(rcvBuf,"%d",&res);
 if(res != 150)
 {
  printf("ftp RETR command result err !=150\r\n");
  return -1;
 }

 /* 客户端创建文件 */ 
 fp = fopen(savePath,"a+");
 if(fp == NULL)
 {
  printf("save file open err\r\n");
  return -1;
 }
 
 while(1)
 {
  /* 客户端通过数据连接 从服务器接收文件内容 */
  rcvLength = recv(dataSock,rcvBuf,100,0);
  if(rcvLength == 100)
  {
   /* 客户端写文件 */ 
   fwrite(rcvBuf,1,rcvLength,fp);
  }
  else
  {
   break;
  }
 }
 /* 客户端接收服务器的响应码和信息,正常为 ”226 Successfully transferred ” */ 
 if(recv(commandSock,rcvBuf,100,0) == -1)
 {
  printf("ftp recv download command err\r\n");
  return -1;
 }
 sscanf(rcvBuf,"%d",&res);
 if(res != 226)
 {
  printf("ftp RETR download result err !=226\r\n");
  return -1;
 }
 
 /* 客户端关闭文件 */ 
 fclose(fp);
 return 0;
}
/**********************************
*功能:退出FTP
*说明:
***********************************/
int ftp_quit(int commandSock)
{
 char sendBuf[100];
 char rcvBuf[100]; 
 int res;
 
 /* 命令 ”RETR filename\r\n” */
 sprintf(sendBuf,"QUIT\r\n");
 /* 客户端发送下载命令到服务器端 */ 
 if(send(commandSock,sendBuf,strlen(sendBuf),0) == -1)
 {
  printf("ftp socket send err\r\n");
  return -1;
 }
 /* 客户端接收服务器的响应码,正常为 ”200 Closes connection.” */ 
 if(recv(commandSock,rcvBuf,100,0) == -1)
 {
  printf("ftp recv login password message err\r\n");
  return -1;
 }
 if(res != 221)
 {
  printf("ftp QUIT command result err !=221\r\n");
  return -1;
 }
 return 0;
}
int main(int argc,char *argv[])
{
 int commandSock;/*命令端口socket文件描述符*/
 int dataSock;/*FTP的数据端口*/
 int res;
 
 printf("main start\r\n");
 /*客户端和 FTP 服务器建立 Socket 连接*/
 commandSock = ftp_commandSocketConnect(FTP_IP,FTP_COMMAND_PORT);
 if(commandSock == -1)
 {
  printf("ftp connect command socket err\r\n");
  close(commandSock);
  return -1;
 }
 printf("connect to command socket\r\n");
 
 /*向服务器发送 USER、PASS 命令登录 FTP 服务器*/
 res = ftp_loginServer(commandSock,FTP_USER_NAME,FTP_USER_PSW);
 if(res == -1)
 {
  printf("ftp login server err\r\n");
  close(commandSock);
  return -1;
 }
 printf("log server sucess\r\n");
 
 /*使用 PASV 命令得到服务器监听的端口号,建立数据连接*/
 dataSock = ftp_dataSocketConnect(commandSock);
 if(dataSock == -1)
 {
  printf("ftp data socket connect err\r\n");
  close(commandSock);
  return -1;
 }
 printf("connect data socket\r\n");
 
 /*使用 RETR 命令下载文件*/
 res = ftp_downloadFile(commandSock,dataSock,DWN_FILE_PATH,SAVE_FILE_PATH);
 if(res == -1)
 {
  printf("ftp download file err\r\n");
  close(commandSock);
  close(dataSock);
  return -1;
 }
 close(dataSock);
 printf("download file ok\r\n");
 
 /*退出FTP*/
 res = ftp_quit(commandSock);
 if(res == -1)
 {
  printf("ftp quit err\r\n");
  close(commandSock);
  return -1;
 }
 close(commandSock);
 printf("ftp test over\r\n");
 return 0;
}

猜你喜欢

转载自blog.csdn.net/fengweibo112/article/details/99682415