ftp客户端的创建

1.本段代码采用了 select I/O端口复用

2.含有三种功能:ls,  上传文件, 下载文件。这是拷贝别人的代码,自己添加了注释,随后会进行修改,

  自己需要的功能:上传文件, 下载文件,  (并且在传输途中,对所有的文件进行openssl加密)

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <netdb.h>
  4 #include <errno.h>
  5 #include <sys/types.h>
  6 #include <sys/stat.h>
  7 #include <fcntl.h>
  8 #include <unistd.h>
  9 #include <string.h>
 10 #include <sys/ioctl.h>
 11 #include <sys/fcntl.h>
 12 
 13 
 14 #define MAXBUF             1024        //宏大小
 15 #define STDIN_FILENO     1            //标准输入
 16 #define STDOUT_FILENO     0            //标准输出
 17 
 18 
 19 #define USERNAME     220            //用户名
 20 #define PASSWORD      331            //密码
 21 #define LOGIN           230            //登录
 22 #define PATHNAME      257            //路径名
 23 #define CLOSEDATA     226            //    
 24 #define ACTIONOK      250            //
 25 
 26 
 27 char *rbuf,*rbuf1,*wbuf,*wbuf1;
 28 
 29 
 30 char filename[100];                    //文件名
 31 char *host;                            //要连接的服务器地址
 32 
 33 
 34 struct sockaddr_in servaddr;        //服务器的地址、端口结构体
 35 
 36 //1.第一步,打开一个TCP链接
 37 int cliopen(char *host,int port);
 38 //
 39 int strtosrv(char *str);
 40 int ftp_get(int sck,char *pDownloadFileName);
 41 int ftp_put(int sck,char *pUploadFileName_s);
 42 void cmd_tcp(int sockfd);                        //
 43 
 44 //主函数
 45 int main(int argc,char *argv[])
 46 {
 47     int fd;
 48 
 49     //判断输入参数
 50     if(0 != argc -2)
 51     {
 52         printf("%s
","missing <hostname>");
 53         exit(0);
 54     }
 55 
 56     //指定服务器地址
 57     host = argv[1];
 58     //指定端口
 59     int port = 21;
 60    
 61     rbuf = (char *)malloc(MAXBUF*sizeof(char));
 62     rbuf1 = (char *)malloc(MAXBUF*sizeof(char));
 63     wbuf = (char *)malloc(MAXBUF*sizeof(char));
 64     wbuf1 = (char *)malloc(MAXBUF*sizeof(char));
 65 
 66     //1.得到已连接的套接字
 67     fd = cliopen(host,port);
 68 
 69     //2.
 70     cmd_tcp(fd);
 71     
 72     exit(0);
 73 }
 74 
 75 
 76 
 77 
 78 //1.第一步,打开一个TCP链接
 79 int cliopen(char *host,int port)
 80 {
 81     int control_sock;
 82 
 83     //1.FTP 自己的传输地址结构体
 84     struct hostent *ht = NULL;
 85 
 86     //2.创建套接字
 87     control_sock = socket(AF_INET,SOCK_STREAM,0);
 88     if(control_sock < 0)
 89     {
 90        printf("socket error
");
 91        return -1;
 92     }
 93 
 94     //3.将IP地址进行转换,变为FTP地址结构体
 95     ht = gethostbyname(host);
 96     if(!ht)
 97     { 
 98         return -1;
 99     }
100     
101    //4.连接服务器,返回套接字
102     memset(&servaddr,0,sizeof(struct sockaddr_in));
103     memcpy(&servaddr.sin_addr.s_addr,ht->h_addr,ht->h_length);
104     servaddr.sin_family = AF_INET;
105     servaddr.sin_port = htons(port);
106     
107     if(connect(control_sock,(struct sockaddr*)&servaddr,sizeof(struct sockaddr)) == -1)
108     {
109         return -1;
110     }
111     return control_sock;
112 }
113 
114 //匹配下载的文件名
115 int s(char *str,char *s2)
116 {
117     //char s1[100];
118      
119     return sscanf(str," get %s",s2) == 1;
120    
121 }
122 
123 //匹配上传的文件名
124 int st(char *str,char *s1)
125 {
126     return sscanf(str," put %s",s1) == 1;
127 }
128 
129 //获取服务器 发送给 客户端的 IP地址 和 端口;
130 int strtosrv(char *str)
131 {
132    int addr[6];
133    //printf("%s
",str);
134    sscanf(str,"%*[^(](%d,%d,%d,%d,%d,%d)",&addr[0],&addr[1],&addr[2],&addr[3],&addr[4],&addr[5]);
135    bzero(host,strlen(host));
136    sprintf(host,"%d.%d.%d.%d",addr[0],addr[1],addr[2],addr[3]);
137    int port = addr[4]*256 + addr[5];
138    return port;
139 }
140 
141 //显示文件列表
142 void ftp_list(int sockfd)
143 {
144     int nread;
145     for(;;)
146     {
147         if((nread = recv(sockfd,rbuf1,MAXBUF,0)) < 0)
148         {
149             printf("recv error
");
150         }
151         else if(nread == 0)
152         {
153             //printf("over
");
154             break;
155         }
156         if(write(STDOUT_FILENO,rbuf1,nread) != nread)
157             printf("send error to stdout
");
158         /*else
159             printf("read something
");*/
160     }
161     if(close(sockfd) < 0)
162         printf("close error
");
163 }
164 
165 //下载文件
166 int ftp_get(int sck,char *pDownloadFileName)
167 {
168    int handle = open(pDownloadFileName,O_WRONLY | O_CREAT | O_TRUNC, S_IREAD| S_IWRITE);
169    int nread;
170    printf("%d
",handle);
171    /*if(handle == -1) 
172        return -1;*/
173 
174     //2. 猜测 ====================应该是将 ssl 接口放在这里,用来传输数据
175    
176    for(;;)
177    {
178        if((nread = recv(sck,rbuf1,MAXBUF,0)) < 0)
179        {
180           printf("receive error
");
181        }
182        else if(nread == 0)
183        {
184           printf("over
");
185           break;
186        }
187     //   printf("%s
",rbuf1);
188        if(write(handle,rbuf1,nread) != nread)
189            printf("receive error from server!");
190        if(write(STDOUT_FILENO,rbuf1,nread) != nread)
191            printf("receive error from server!");
192    }
193        if(close(sck) < 0)
194            printf("close error
");
195 }
196 
197 
198 //上传文件
199 int ftp_put(int sck,char *pUploadFileName_s)
200 {
201    //int c_sock;
202    int handle = open(pUploadFileName_s,O_RDWR);
203    int nread;
204    if(handle == -1)
205        return -1;
206    //ftp_type(c_sock,"I");
207 
208    //3. 猜测 ====================应该是将 ssl 接口放在这里,用来传输数据
209    for(;;)
210    {
211        if((nread = read(handle,rbuf1,MAXBUF)) < 0)
212        {
213             printf("read error!");
214        }
215        else if(nread == 0)
216           break;
217        if(write(STDOUT_FILENO,rbuf1,nread) != nread)
218             printf("send error!");
219        if(write(sck,rbuf1,nread) != nread)
220             printf("send error!");
221    }
222    if(close(sck) < 0)
223         printf("close error
");
224 }
225 
226 
227 
228 //各种参数的执行
229 void cmd_tcp(int sockfd)
230 {
231     int maxfdp1,nread,nwrite,fd,replycode,tag=0,data_sock;
232     int port;
233     char *pathname;
234     fd_set rset;                //可读文件描述符集合
235     FD_ZERO(&rset);                //清空可读文件描述符集合
236     maxfdp1 = sockfd + 1;        //最大套接字
237 
238     for(;;)
239     {
240         //1.将  标准输入加入 可读文件描述符集合
241          FD_SET(STDIN_FILENO,&rset);
242         //2.将  命令套接字   加入可读文件描述符集合
243          FD_SET(sockfd,&rset);
244 
245         //3.监听读事件
246          if(select(maxfdp1,&rset,NULL,NULL,NULL)<0)
247          {
248              printf("select error
");
249          }
250          //4.判断标准输入是否有读事件
251          if(FD_ISSET(STDIN_FILENO,&rset))
252          {
253              //5.清空读缓冲区 和 写缓冲区
254               bzero(wbuf,MAXBUF);          //zero
255               bzero(rbuf1,MAXBUF);
256               
257               if((nread = read(STDIN_FILENO,rbuf1,MAXBUF)) <0)
258                    printf("read error from stdin
");
259               nwrite = nread + 5;
260 
261             //=======这里不懂,replycode  什么时候赋的值
262 
263             //6.命令套接字中  写入  用户名
264               if(replycode == USERNAME) 
265               {
266                   sprintf(wbuf,"USER %s",rbuf1);
267               
268                  if(write(sockfd,wbuf,nwrite) != nwrite)
269                  {
270                      printf("write error
");
271                  }
272                  //printf("%s
",wbuf);
273                  //memset(rbuf1,0,sizeof(rbuf1));
274                  //memset(wbuf,0,sizeof(wbuf));
275                  //printf("1:%s
",wbuf);
276               }
277 
278             //7.命令套接字中  写入  密码                
279               if(replycode == PASSWORD)
280               {
281                    //printf("%s
",rbuf1);
282                    sprintf(wbuf,"PASS %s",rbuf1);
283                    if(write(sockfd,wbuf,nwrite) != nwrite)
284                       printf("write error
");
285                    //bzero(rbuf,sizeof(rbuf));
286                    //printf("%s
",wbuf);
287                    //printf("2:%s
",wbuf);
288               }
289               
290               if(replycode == 550 || replycode == LOGIN || replycode == CLOSEDATA || replycode == PATHNAME || replycode == ACTIONOK)
291               {
292               if(strncmp(rbuf1,"pwd",3) == 0)
293               {   
294                      //printf("%s
",rbuf1);
295                      sprintf(wbuf,"%s","PWD
");
296                      write(sockfd,wbuf,4);
297                      continue; 
298                  }
299                  if(strncmp(rbuf1,"quit",4) == 0)
300                  {
301                      sprintf(wbuf,"%s","QUIT
");
302                      write(sockfd,wbuf,5);
303                      //close(sockfd);
304                     if(close(sockfd) <0)
305                        printf("close error
");
306                     break;
307                  }
308                  if(strncmp(rbuf1,"cwd",3) == 0)
309                  {
310                      //sprintf(wbuf,"%s","PASV
");
311                      sprintf(wbuf,"%s",rbuf1);
312                      write(sockfd,wbuf,nread);
313                      
314                      //sprintf(wbuf1,"%s","CWD
");
315                      
316                      continue;
317                  }
318                  
319                  if(strncmp(rbuf1,"ls",2) == 0)
320                  {
321                      tag = 2;            //显示文件 标识符
322                      //printf("%s
",rbuf1);
323                      sprintf(wbuf,"%s","PASV
");
324                      //printf("%s
",wbuf);
325                      write(sockfd,wbuf,5);
326                      //read
327                      //sprintf(wbuf1,"%s","LIST -al
");
328                      nwrite = 0;
329                      //write(sockfd,wbuf1,nwrite);
330                      //ftp_list(sockfd);
331                      continue;    
332                  }
333                  //8.下载文件
334                  if(strncmp(rbuf1,"get",3) == 0)
335                  {
336                      tag = 1;            //下载文件标识符
337 
338                      //被动传输模式    
339                      sprintf(wbuf,"%s","PASV
");                   
340                      //printf("%s
",s(rbuf1));
341                      //char filename[100];
342                      s(rbuf1,filename);
343                      printf("%s
",filename);
344                      write(sockfd,wbuf,5);
345                      continue;
346                  }
347                  
348                  if(strncmp(rbuf1,"put",3) == 0)
349                  {
350                      tag = 3;            //上传文件标识符
351                      sprintf(wbuf,"%s","PASV
");
352 
353                     //把内容赋值给  读缓冲区
354                      st(rbuf1,filename);
355                      printf("%s
",filename);
356                      write(sockfd,wbuf,5);
357                      continue;
358                  }
359               } 
360                     /*if(close(sockfd) <0)
361                        printf("close error
");*/
362          }
363          if(FD_ISSET(sockfd,&rset))
364          {
365          //9.清空读缓冲区 和 写缓冲区
366              bzero(rbuf,strlen(rbuf));
367          //10.读套接字中的内容
368              if((nread = recv(sockfd,rbuf,MAXBUF,0)) <0)
369                   printf("recv error
");
370              else if(nread == 0)
371                break;
372 
373            //比较
374              if(strncmp(rbuf,"220",3) ==0 || strncmp(rbuf,"530",3)==0)
375              {
376                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
377                     printf("write error to stdout
");*/
378 
379                  //链接字符串
380                  strcat(rbuf,"your name:");
381                 
382                  //printf("%s
",rbuf);
383                  nread += 12;
384                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
385                     printf("write error to stdout
");*/
386                  replycode = USERNAME;
387              }
388              if(strncmp(rbuf,"331",3) == 0)
389              {
390                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
391                     printf("write error to stdout
")*/;
392                 strcat(rbuf,"your password:");
393                 nread += 16;
394                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
395                     printf("write error to stdout
");*/
396                 replycode = PASSWORD;
397              }
398              if(strncmp(rbuf,"230",3) == 0)
399              {
400                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
401                     printf("write error to stdout
");*/
402                 replycode = LOGIN;
403              }
404              if(strncmp(rbuf,"257",3) == 0)
405              {
406                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
407                     printf("write error to stdout
");*/
408                 replycode = PATHNAME;  
409              }
410              if(strncmp(rbuf,"226",3) == 0)
411              {
412                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
413                     printf("write error to stdout
");*/
414                 replycode = CLOSEDATA;
415              }
416              if(strncmp(rbuf,"250",3) == 0)
417              {
418                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
419                     printf("write error to stdout
");*/
420                 replycode = ACTIONOK;
421              }
422              if(strncmp(rbuf,"550",3) == 0)
423              {
424                 replycode = 550;
425              }
426              /*if(strncmp(rbuf,"150",3) == 0)
427              {
428                 if(write(STDOUT_FILENO,rbuf,nread) != nread)
429                     printf("write error to stdout
");
430              }*/    
431              //fprintf(stderr,"%d
",1);
432              if(strncmp(rbuf,"227",3) == 0)
433              {
434                 //printf("%d
",1);
435                 /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
436                    printf("write error to stdout
");*/
437 
438                 //获取服务器返回的 接收数据的端口,和地址
439                 int port1 = strtosrv(rbuf);
440                 printf("%d
",port1);
441                 printf("%s
",host);
442 
443                 //创建新的传输数据的套接字?
444                 //1. 猜测 ====================应该是将 ssl 接口放在这里,用来传输数据
445                 data_sock = cliopen(host,port1);
446         
447 
448 
449 //bzero(rbuf,sizeof(rbuf));
450                 //printf("%d
",fd);
451                 //if(strncmp(rbuf1,"ls",2) == 0)
452                 if(tag == 2)
453                 {
454                    write(sockfd,"list
",strlen("list
"));
455                    ftp_list(data_sock);
456                    /*if(write(STDOUT_FILENO,rbuf,nread) != nread)
457                        printf("write error to stdout
");*/
458                    
459                 }
460                 //else if(strncmp(rbuf1,"get",3) == 0)
461                 else if(tag == 1)
462                 {
463                     //sprintf(wbuf,"%s","RETR
");
464                     //printf("%s
",wbuf);
465                     //int str = strlen(filename);
466                     //printf("%d
",str);
467                     sprintf(wbuf,"RETR %s
",filename);
468                     printf("%s
",wbuf);
469                     //int p = 5 + str + 1;
470 
471                     //命令套接字中写入  下载文件命令
472                     printf("%d
",write(sockfd,wbuf,strlen(wbuf)));
473                     //printf("%d
",p);
474 
475                     //下载文件 
476                     ftp_get(data_sock,filename);
477                 }
478                 else if(tag == 3)
479                 {
480 
481                     // 上传文件
482                     sprintf(wbuf,"STOR %s
",filename);
483                     printf("%s
",wbuf);
484                     write(sockfd,wbuf,strlen(wbuf));
485                     ftp_put(data_sock,filename);
486                 }
487                 nwrite = 0;     
488              }
489              /*if(strncmp(rbuf,"150",3) == 0)
490              {
491                  if(write(STDOUT_FILENO,rbuf,nread) != nread)
492                      printf("write error to stdout
");
493              }*/
494              //printf("%s
",rbuf);
495              if(write(STDOUT_FILENO,rbuf,nread) != nread)
496                  printf("write error to stdout
");
497              /*else 
498                  printf("%d
",-1);*/            
499          }
500     }
501 }
原文地址:https://www.cnblogs.com/yyx1-1/p/6119245.html