⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downfromftp.c

📁 linux下http和ftp下载工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
* File name: DownFromFTP.c
* Author: Version: Date: likun
* Description: 下载管理模块的实现
*
* Others:
* Function List:
* 1. ....
* History:
* 1. Date:2008-3-31
* Author:likun create this file
* Modification:
* 2. ...
*************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include"DownFromFTP.h"
#include"GenFunc.h"


#ifdef __cplusplus

extern "C" {
#endif

#define Ftp_Debug(fmt,arg...)  {\
           fprintf(stderr,"\r\n%s:%04d, "fmt, __FILE__, __LINE__, ##arg);\
        }

/* the following function parse the url and interact 
with server for some information like file length etc.*/
int GetFtpUrlInfo(const char *url, DLoadFileInfo *pDloadFile)
{
    char head[1024],length1[32];
    char c_port[8];
    int iport=0;//sign the first time to see : like www.xxx.com:8000/name this is the position of :
    char dataget[1024]="";
    int i,i_sock,j;
    int length;

    if((!url) || (!pDloadFile))
        return -1;
    
    length = strlen(url);
    
    if(!strncasecmp(url,"ftp://",6))
        pDloadFile->hosttype=DLOAD_PROTOCOL_FTP;
	else
    {
        Ftp_Debug("You must input a url start with ftp://");
        return -1;
    }   

    if(strstr(url,"@")==NULL)
    {
		for(i=0;i<=strlen(url)-6;i++)
    	{
			if(*(url+6+i)==':')
    		{
				iport=i;
				continue;
			}

			if(*(url+6+i)=='/')
    		{
				if(iport!=0)
    			{
					snprintf(pDloadFile->host,iport+1,"%s",url+6);
					sprintf(pDloadFile->path,"/%s",url+6+i+1);
					snprintf(c_port,i-iport,"%s",url+6+iport+1);
					pDloadFile->ftpPort=atoi(c_port);
				}
                else
    			{
					snprintf(pDloadFile->host,i+1,"%s",url+6);
					sprintf(pDloadFile->path,"/%s",url+6+i+1);
				}
				break;
			}
		}
        
		for(i=length-1;i>=0;i--)
    	{
			if(*(url+i)=='/')
    		{
				sprintf(pDloadFile->filename,"%s",url+i+1);
				break;
			}
		}
    }
    else
    {
    	for(i=0;i<=strlen(url)-6;i++)
    	{
			if(*(url+6+i)==':')
    		{
				iport=i;
				continue;
			}

    		if(*(url+6+i)=='@')
    		{
				if(iport!=0)
    			{
					snprintf(pDloadFile->user,iport+1,"%s",url+6);
					snprintf(pDloadFile->pass,i-iport,"%s",url+6+iport+1);
				}
				else
    			{
					snprintf(pDloadFile->user,i+1,"%s",url+6);
					sprintf(pDloadFile->pass,"%s",url+6+i+1);
				}
				sprintf(url,"ftp://%s",url+8+strlen(pDloadFile->user)+strlen(pDloadFile->pass));
				GetFtpUrlInfo(url,pDloadFile);
				return 0;

    		}
    	}
    }

	i_sock = GetConnectSocket(pDloadFile->host,pDloadFile->ftpPort);		
    j = recv(i_sock,dataget,1024,0);
    memset(dataget, 0, 1024);

    sprintf(head,"USER %s\r\n\r\n", pDloadFile->user);
    if(send(i_sock,head,strlen(head),0)!=strlen(head))
    {
        Ftp_Debug("Error in sending HEAD");
        close(i_sock);
        return -1;
    }
    if(ReadEn(i_sock,5)>0)
    {
    	j = recv(i_sock,dataget,1024,0);
    }
    
    if(strstr(dataget,"230")==NULL)	//230 Any password will work
    {
        memset(dataget, 0, 1024);
    	sprintf(head,"PASS %s\r\n\r\n",pDloadFile->pass);
    	if(send(i_sock,head,strlen(head),0)!=strlen(head))
        {
            Ftp_Debug("Error in sending HEAD");
            return -1;
        }
    	sleep(1);
    	if(ReadEn(i_sock,5)>0)
    	{
    		j=recv(i_sock,dataget,1024,0);
    	}
    }
    
    memset(dataget, 0, 1024);
    sprintf(head,"SIZE %s\r\n\r\n", pDloadFile->path);
    if(send(i_sock,head,strlen(head),0)!=strlen(head))
    {
        Ftp_Debug("Error in sending HEAD");
        close(i_sock);
        return -1;
    }
    if(ReadEn(i_sock,5) > 0)
    recv(i_sock, dataget, 1024, 0);
    if(strstr(dataget,"213")!=NULL)
    {
    	i=1;
    	while(1)
    	{
    		if(*(strstr(dataget,"213")+i)=='\n')break;
    		i++;
    	}
    		
    	snprintf(length1,i-4,"%s",strstr(dataget,"213")+4);
    	pDloadFile->filelength = atoi(length1);
    	if(pDloadFile->filelength==0)
    	{
    		close(i_sock);
    		sleep(1);
    		GetFtpUrlInfo(url, pDloadFile);
    		return 0;
    	}
    }
    else
    {
    	close(i_sock);
    	sleep(1);
    	GetFtpUrlInfo(url, pDloadFile);
    	return 0;
    }

    
    Ftp_Debug("host: %s,path: %s, filename:%s,user:%s, pass:%s",
        pDloadFile->host,pDloadFile->path,pDloadFile->filename, pDloadFile->user,pDloadFile->pass);
    close(i_sock);
    return 0;
}


/*this function used to download assigned file
from a1 bytes to a2 bytes from host, try 5 times */
int DownLoadFtp(DloadForCreatThread *pCreatThread)
{
#define FALSE 0
#define TRUE 1

    char get[256],dataget[512];
    char buf[1024];
    char port1[8],port2[8];//227 Entering Passive Mode (192,168,8,30,6,32) 6 is stored in port1, while 32 is stored in port2
    char headhost[256];
    char range[32];
    float f;
    unsigned long timeuse;
    struct arg *s_info;

    int connected = FALSE,bytesget;//bytesget stans for how many bytes get one time
    int i,j,boolprint = 0;
    int sock,sockdata;//sockdata is used to download ftp data through another sock because ftp use 2 pipes
    int readen, portthread=0, nextthread=0;
    int inflen,index=0,offset=0;
    int curThreadId = pCreatThread->threadId;
    FtpHttpDLoadInfo *pDloadInfo = pCreatThread->pInfo;
    DLoadFileInfo *pTmpFileInfo = &(pDloadInfo->FileInfo);
    s_info = &(pTmpFileInfo->astPthread[curThreadId]);
    int bytesleft =(s_info->a2)-(s_info->a1)+1;

    /*等待上一个下载线程开始,如果不进行该步
    操作,前面的数据有永远不能下载的可能*/
    if(curThreadId != 0)
    {
    	while(pTmpFileInfo->astPthread[curThreadId-1].booldown==0){
    		sleep(1);
	    }
    }

    /*如果该线程已经被前一线程帮助下载,那么退出该线程*/
    if((s_info->booldown==1) && (s_info->allowotherdown==1))
    {
        free(pCreatThread);
        return 0;
    }
    
    while(1)
    {
        //connect server
        if((sock=GetConnectSocket(pTmpFileInfo->host,pTmpFileInfo->ftpPort))<=0)
            sleep(1);
        else{
   		    connected=TRUE;
   		    break;
        }
    }

    /*连接服务器成功*/
    if(connected)
    {
        if(ReadEn(sock,5)>0)
        {
            recv(sock,dataget,512,0);
	        memset(dataget, 0, 512);
        }
    	sprintf(headhost,"USER %s\r\n\r\n",pTmpFileInfo->user);

    	if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost))
        {
    		close(sock);
    		sleep(5);
    		
       		DownLoadFtp(pCreatThread);
    		return 0;
        }
        
    	if(ReadEn(sock,5)>0)
        {
    	    recv(sock,dataget,512,0);
	        memset(dataget, 0, 512);
    	}
    	
    	sprintf(headhost,"PASS %s\r\n\r\n",pTmpFileInfo->pass);
    	if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost))
        {
    		close(sock);
    		sleep(5);
       		DownLoadFtp(pCreatThread);
    		return 0;
        }
    	
    	recv(sock,dataget,512,0);
        /*Service not available, closing control connection*/
    	if(strstr(dataget,"421 No more connection")!=NULL){
    		close(sock);
    		sleep(5);
    		
       		DownLoadFtp(pCreatThread);
    		return 0;
    	}

        memset(dataget, 0, 512);

        /*The data are sent as contiguous bits which, for transfer,
          are packed into the 8-bit transfer bytes*/
    	sprintf(headhost,"TYPE I\r\n\r\n");
            
    	if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost)){
    		close(sock);
    		sleep(5);
       		DownLoadFtp(pCreatThread);
    		return 0;
            }
    	
    	recv(sock,dataget,512,0);
        memset(dataget, 0, 512);

        /*Passive mode*/
    	sprintf(headhost,"PASV\r\n\r\n");

    	if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost)){
       		printf("Error in sending HEAD\n");
    		close(sock);
    		sleep(5);
       		DownLoadFtp(pCreatThread);
    		return 0;
            }
    	
    	recv(sock,dataget,512,0);
        while(strstr(dataget,"227")==NULL)
        {
	        memset(dataget, 0, 512);
        	if(ReadEn(sock,5)>0)
            {
        		recv(sock,dataget,512,0);
        		
        	}
        }

        /*服务器端进行应答,应答包括服务器的IP地址和一个暂时的端口,
        这个暂时的端口是客户端在打开数据传输连接时应该使用的端口
        例子:服务器对PASV命令的回应,服务器告诉客户端它在端口5365(192,168,179,100,20
        ,245)上进行监听,计算端口的方法是20*256+245=5365;
        */
        if(strstr(dataget,"227 Entering Passive Mode")!=NULL)
        {
    		j=4;
    		i=0;
    		while(j>=1)
            {
    			if(*(strstr(dataget,"227 Entering Passive Mode")+i)==',')j--;
    			i++;
    		}
    		j=i+1;
    		while(1){
    			if(*(strstr(dataget,"227 Entering Passive Mode")+j)==',')break;
    			j++;
    		}
    		
    		snprintf(port1,j-i+1,"%s",strstr(dataget,"227 Entering Passive Mode")+i);
    		i=j+1;
    		while(1){
    			if(*(strstr(dataget,"227 Entering Passive Mode")+i)==')')break;
    			i++;
    		}
    		snprintf(port2,i-j,"%s",strstr(dataget,"227 Entering Passive Mode")+j+1);
    		portthread=256*atoi(port1)+atoi(port2);		
    	}
    	if(portthread==0)
        {
    		close(sock);
    		sleep(5);
    		DownLoadFtp(pCreatThread);
    		return 0;
    	}   
        
        memset(dataget, 0, 512);
        /*The argument field represents the server marker
          at which file transfer is to be restarted.*/
    	sprintf(headhost,"REST %d\r\n\r\n",s_info->a1);
    	if(send(sock,headhost,strlen(headhost),0)!=strlen(headhost))
        {
    		close(sock);
    		sleep(5);
       		DownLoadFtp(pCreatThread);
    		return 0;
        }
    	if(ReadEn(sock,5)>0)
        {
    	    recv(sock,dataget,512,0);
            Ftp_Debug("REST from: %d", s_info->a1);
            Ftp_Debug("Command REST recv: %s\r\n", dataget);
            if((strstr(dataget,"202 Command not implemented")!=NULL)
                    || (strstr(dataget,"502 Command not implemented")!=NULL))
                Ftp_Debug("Command REST not implemented\r\n");
	        memset(dataget, 0, 512);
        }
   

        sprintf(get,"RETR %s\r\n\r\n",pTmpFileInfo->path);
        if(send(sock,get,strlen(get),0)!=strlen(get))
        {
        	Ftp_Debug("Error in sending get");
            close(sock);
            sleep(5);
        	DownLoadFtp(pCreatThread);
            return 0;
        }
    	if(ReadEn(sock,5)>0)
        {
    	    recv(sock,dataget,512,0);
            Ftp_Debug("Command RETR recv: %s\r\n", dataget);
            if((strstr(dataget,"202 Command not implemented")!=NULL)
                    || (strstr(dataget,"502 Command not implemented")!=NULL))
                Ftp_Debug("Command RETR not implemented\r\n");
	        memset(dataget, 0, 512);
        }

        /* likun 打开/创建下载到本地的文件*/
        s_info->fd = open(pTmpFileInfo->localpath,O_WRONLY|O_CREAT,0644);
    	
        lseek(s_info->fd,s_info->a1,0);
            
        connected = FALSE;
        /*使用server指定的端口进行连接,重试5次*/
        for(i=0;i<=5;i++)
        {
            if((sockdata = GetConnectSocket(pTmpFileInfo->host,portthread))<= 0)
            	sleep(1);
            else{
            	    connected=TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -