//下载的实现函数 int ftp_download(int control_sockfd) { int pasv_or_port;// 定义the ftp协议的两种不同工作mode int recvbytes,sendbytes; char sendline[1024],recvline[1024]; struct sockaddr_in serv_addr; FILE *fd; int i,j; int data_sockfd; //rest ftp_rest(control_sockfd); //type zeromery(recvline,1024); zeromery(sendline,1024); strcat(sendline,"TYPE "); strcat(sendline,"I"); strcat(sendline,"\r\n"); sendbytes=send(control_sockfd,sendline,strlen(sendline),0); if(sendbytes<0) { printf(" type send is error!\n"); } recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0); if(strncmp(recvline,"200",3)==0) { printf("使用二进制传输数据\n"); } else { printf("type recv is error!\n"); } if(npsupport==1) { //open the file int size; char localpathname[60];//预打开的文件路径字符串 int flags; char pathname[60]; unsigned int mode; //用户来选择pasv 或者是 port mode char selectdata_mode_tran[1024]; zeromery(selectdata_mode_tran,1024); zeromery(sendline,1024); zeromery(recvline,1024); pasv_or_port=0;//(默认是pasv模式) //pasv mode if(pasv_or_port==0) { strcat(sendline,"PASV"); strcat(sendline,"\r\n"); sendbytes=send(control_sockfd,sendline,strlen(sendline),0); if(sendbytes<0) { printf("pasv send is error!\n"); } zeromery(recvline,1024); recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0); if(recvbytes<0) { printf("pasv recv is error!\n"); } if(strncmp(recvline,"227",3)==0) { char buf[55]; snprintf(buf,51,">>> %s\n",recvline); printf("%s\n",buf); } else { printf("pasv recv is error!\n"); } //处理ftp server 端口 char *ptr1,*ptr2; char num[1024]; zeromery(num,1024); //取低位字节 ptr1=recvline+strlen(recvline); while(*(ptr1)!=')') { ptr1--; } ptr2=ptr1; while(*(ptr2)!=',') ptr2--; strncpy(num,ptr2+1,ptr1-ptr2-1); i=atoi(num);//将字符串转换成整数 //取高位字节 zeromery(num,1024); ptr1=ptr2; ptr2--; while(*(ptr2)!=',') ptr2--; strncpy(num,ptr2+1,ptr1-ptr2-1); j=atoi(num); //初始化服务器数据连接时的端口信息 int data_serviceport; data_serviceport=j*256+i; data_sockfd=socket(AF_INET,SOCK_STREAM,0); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=INADDR_ANY; serv_addr.sin_port=htons(data_serviceport); if(connect(data_sockfd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))==-1) { printf("pasv data connect is error!\n"); } printf("remote-file-pathname="); scanf("%s",pathname); printf("local-file-pathname="); scanf("%s",localpathname); printf("local:%s remore:%s\n",localpathname,pathname); fd=fopen(localpathname,"w+"); if(fd==NULL) { printf("cannot open file\n"); exit(1); } //send the command retr; zeromery(sendline,1024); zeromery(recvline,1024); strcat(sendline,"RETR "); strcat(sendline,pathname); strcat(sendline,"\r\n"); printf("%s\n",sendline); sendbytes=send(control_sockfd,sendline,strlen(sendline),0); if(sendbytes<0) { printf("retr send is error!\n"); } recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0); if(recvbytes<0) { printf("retr recv is error!\n"); } if(strncmp(recvline,"400",3)>0) { printf("return is error!\n"); } } //port mode /*if(pasv_or_port==1) { data_sockfd=socket(AF_INET,SOCK_STREAM,0); if(data_sockfd<0) { printf("创建数据端口连接失败!\n"); } serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=INADDR_ANY; serv_addr.sin_port=htons(SERV_PORT); int ret; int addrlen; ret=sizeof(struct sockaddr_in); getsockname(data_sockfd,(SA*)&serv_addr,&ret); //处理port 后面要带的参数 char ip[1024]; int i,j; char data[1024]; zeromery(ip,1024); zeromery(data,1024); inet_ntop(AF_INET,&(serv_addr.sin_addr),ip,sizeof(ip)); printf("%s\n",ip); i=data_sockfd/256; j=data_sockfd%256; //将点分十进制的点转换为逗号。 char *ptr1; ptr1=ip; while(*(ptr1)!='/0') { if(*(ptr1)=='.') { *(ptr1)=','; } ptr1++; } strcat(sendline,"PORT "); strcat(sendline,ip); strcat(sendline,","); strcat(sendline,itoa(i,data,10)); strcat(sendline,","); strcat(sendline,itoa(j,data,10)); strcat(sendline,"\r\n"); printf("--->%s\n",sendline); sendbytes=send(control_sockfd,sendline,strlen(sendline),0); if(sendbytes<0) { printf("port send is error!\n"); exit(1); } recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0); if(strncmp(recvline,"200",3)==0) { printf("%s\n",recv); } else { printf("port recv is error!\n"); } }*/ //begin to transpotr data sleep(1); int flag=0; char buffer[65536]; recvdata: zeromery(buffer,1024); recvbytes=recv(data_sockfd,buffer,sizeof(buffer),0); if(recvbytes<0) { close(data_sockfd); goto end; } fwrite(buffer,1,recvbytes,fd); zeromery(recvline,1024); recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0); if(flag==0) { if(strncmp(recvline,"226",3)!=0) { flag=1; goto recvdata; } } end: if(flag!=1) { zeromery(recvline,1024); shutdown(data_sockfd,SHUT_WR); close(data_sockfd); } close(data_sockfd); /* int err; char buffer[65535]; err=read(data_sockfd,buffer,sizeof(buffer)); sleep(5); fwrite(buffer,1,err,fd); sleep(5); zeromery(recvline,1024); recvbytes=recv(control_sockfd,recvline,sizeof(recvline),0); if(strncmp(recvline,"226",3)==0) { end: printf("226 transfer complete\n"); close(data_sockfd); }*/ return 0; } }
// // To transfer data, we do these things in order as specifed by // the RFC. // // First, we tell the other side to set up a data line. This // is done by opendataconn() which sets up the socket. When we do that, // the other side detects a connection attempt, so it knows we're // there. Then tell the other side (by using listen()) that we're // willing to receive a connection going to our side. // // Initialize the data connection prior to a transfer operation // Send the PORT command followed by the optional REST command for a resume // Finally send the LIST, RETR, or STOR command // // Returns >= 0 (socket) for success // Returns -2 if cmd failed // Returns -3 under some (forgotten) circumstances // Returns -1 for other errors // static int dataconna( struct ftp_info *info, int restart, const char *fmt, ... ) { struct opusftp_globals *ogp = info->fi_og; va_list ap; // For varargs int ts, ds = -1; // Temporary socket, Data socket struct linger linger = { 1, 120 }; // Socket option int tos = IPTOS_THROUGHPUT; // Another socket option struct sockaddr_in from; // Socket address int reply; BOOL okay = FALSE; if ((ts = opendataconn( ogp, info )) >= 0) { okay = TRUE; // Have the system make an effort to deliver any unsent data // even after we close the connection setsockopt( ts, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger) ); // Data connection is a non-interactive data stream, so // high throughput is desired, at the expense of low // response time setsockopt( ts, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos) ); // Resuming a transfer? if (restart) { // Can we use REST command? if (!(info->fi_flags & FTP_NO_REST)) { // Can TIMEOUT ftp_rest( info, restart ); } } // Result if something failed after opendataconn and before here ds = -3; } if (okay) { va_start( ap, fmt ); // Send main command - Can TIMEOUT reply = vftpa( info, fmt, ap ); va_end( ap ); if (reply/100 == PRELIM || ((info->fi_flags & FTP_FEAT_MLST) && reply == 200)) // better check the actual command? { LONG len = sizeof(from); // Sendport mode? if ((info->fi_flags & FTP_NO_PASV) || !(info->fi_flags & FTP_PASSIVE)) { ds = accept( ts, (struct sockaddr*)&from, &len ); CloseSocket( ts ); } // Passive mode? else { ds = ts; } } else ds = -2; } return ds; }