用HTTP代理下载文件

 
  1. //用HTTP代理下载文件详例
  2. //代码如下:
  3. //(1)一些基本变量
  4. SOCKET HTTPSocket   = NULL; // 主socket
  5. struct sockaddr_in SocketAddr = {0}; // address socket
  6. struct sockaddr_in BindSocket = {0}; // for bind
  7. int m_nRecvTimeout; // recieve timeout
  8. int m_nSendTimeout; // send timeout
  9. WSADATA wsaData;
  10. //要下载文件部分.
  11. //在BindSocket.sin_addr.s_addr = inet_addr (strHost)时,只能使用ip地址
  12. //如果谁知道更好的方法,别忘了告诉我一下。
  13. CString strHost="111.111.111.111 ";
  14. CString DownLoadAddress="http://blog.csdn.net/andylin02";
  15. CString hostFile="logo.gif";
  16. int HttpPort=80;
  17. //(2)一些函数,用来取得http头,和获取文件大小 
  18. int GetFileLength(char *httpHeader)
  19. {
  20.     CString strHeader;
  21.     int local;
  22.     strHeader=(CString)httpHeader;
  23.     local=strHeader.Find("Content-Length",0);
  24.     local+=16;
  25.     strHeader.Delete(0,local);
  26.     local=strHeader.Find("/r");
  27.     strHeader.SetAt(local,'/0');
  28.     
  29.     char temp[30];
  30.     strcpy(temp,strHeader.GetBuffer(strHeader.GetLength()));
  31.     
  32.     return atoi(temp);
  33. }
  34. int GetHttpHeader(SOCKET sckDest, char *str)
  35. {
  36.     BOOL m_bResponsed=0;
  37.     int m_nResponseHeaderSize;
  38.     if(!m_bResponsed)
  39.     {
  40.         char c = 0;
  41.         int nIndex = 0;
  42.         BOOL bEndResponse = FALSE;
  43.         while(!bEndResponse && nIndex < 1024)
  44.         {
  45.             recv(sckDest,&c,1,0);
  46.             str[nIndex++] = c;
  47.             if(nIndex >= 4)
  48.             {
  49.                 if(str[nIndex - 4] == /'/r/' && str[nIndex - 3] == /'/n/'
  50.                     && str[nIndex - 2] == /'/r/' && str[nIndex - 1] == /'/n/')
  51.                     bEndResponse = TRUE;
  52.             }
  53.         }
  54.         m_nResponseHeaderSize = nIndex;
  55.         m_bResponsed = TRUE;
  56.     }
  57.     return m_nResponseHeaderSize;
  58. }
  59. //(3)用来发送的部分
  60. void szcopy(char* dest,const char* src,int nMaxBytes)
  61. {
  62.     int i_cntr=0;
  63.     while ((src[i_cntr]!=/'/0/') || (i_cntr<nMaxBytes))
  64.     {
  65.         dest[i_cntr]=src[i_cntr++];
  66.     }
  67.     dest[i_cntr]=/'/0/';
  68. }
  69. BOOL SocketSend(SOCKET sckDest,const char* szHttp)
  70. {
  71.     char szSendHeader[MAXHEADERLENGTH];
  72.     int iLen=strlen(szHttp);
  73.     szcopy(szSendHeader,szHttp,iLen);
  74.     if(send (sckDest ,(const char FAR *)szSendHeader ,iLen ,0)==SOCKET_ERROR)
  75.     {
  76.         closesocket(sckDest);
  77.         AfxMessageBox("Error when send");
  78.         return FALSE;
  79.     }
  80.     return TRUE;
  81. }
  82. BOOL SocketSend(SOCKET sckDest,CString szHttp)
  83. {
  84.     int iLen=szHttp.GetLength();
  85.     if(send (sckDest,szHttp,iLen,0)==SOCKET_ERROR)
  86.     {
  87.         closesocket(sckDest);
  88.         AfxMessageBox("Error when send");
  89.         return FALSE;
  90.     }
  91.     return TRUE;
  92. }
  93. //(4)用于连接的函数
  94. //这里是做了一些连接用的操作,分了两种情况
  95. //   1)如果没有使用代理,则直接连到你指定的计算机
  96. //  2)如果使用了代理,则直接连到代理
  97. BOOL CDLAngelDlg::ConnectHttp()
  98. {
  99.     message="正在建立连接/n";
  100.     UpdateData(TRUE);
  101.     if(m_combo == "HTTP"// m_combo 一个下拉条
  102.     {
  103.         HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  104.         SocketAddr.sin_addr.s_addr = inet_addr (m_ProxyAddr);
  105.         SocketAddr.sin_family=AF_INET;
  106.         SocketAddr.sin_port=htons(atoi(m_Port));
  107.         struct fd_set fdSet;
  108.         struct timeval tmvTimeout={0L,0L};
  109.         FD_ZERO(&fdSet);
  110.         FD_SET(HTTPSocket, &fdSet);
  111.         if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)
  112.         {
  113.             closesocket(HTTPSocket);
  114.             AfxMessageBox("Error when select.");
  115.             return 0;
  116.         }
  117.         if (connect(HTTPSocket, (const struct sockaddr *)&SocketAddr, sizeof(SocketAddr))==SOCKET_ERROR)
  118.         {
  119.             message="/n代理连接失败/n";
  120.             m_message.CleanText();
  121.             m_message.AddText(message);
  122.             return 0;
  123.         }
  124.         // 发送CONNCET请求令到代理服务器,用于和代理建立连接
  125.         //代理服务器的地址和端口放在m_ProxyAddr,m_Port 里面
  126.         CString temp;
  127.         char tmpBuffer[1024];
  128.         temp.Format("CONNECT %s:%s HTTP/1.1/r/nUser-Agent: MyApp/0.1/r/n/r/n",m_ProxyAddr,m_Port);
  129.         if(!SocketSend(HTTPSocket,temp))
  130.         {
  131.             message="连接代理失败";
  132.             return 0;
  133.         }
  134.         // 取得代理响应,如果连接代理成功,代理服务器将返回200 Connection established
  135.         GetHttpHeader(HTTPSocket,tmpBuffer);
  136.         temp=tmpBuffer;
  137.         if(temp.Find("HTTP/1.0 200 Connection established",0)==-1)
  138.         {
  139.             message="连接代理失败/n";
  140.             return 0;
  141.         }
  142.         message="代理连接完成/n";
  143.         m_message.AddText("代理连接完成/n");
  144.         return 1; // ----------〉这里是应该注意的,连接到代理后,就可以返回了,不需要再连接网上的另外一台机,代理服务器会自动转发数据,所以,连接完代理就像连接到网上另外一台机一样
  145.     }
  146.     else if(m_combo=="Socks4"// 这个,是为了给其他代理做准备
  147.     {
  148.         MessageBox("请注意,现在无法使用代理功能!");
  149.     }
  150.     else if(m_combo=="Socks5")
  151.     {
  152.         MessageBox("请注意,现在无法使用代理功能!");
  153.     }
  154.     // 如果没有使用代理,就要连接到网上的另一台机
  155.     // 准备socket
  156.     HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  157.     if (HTTPSocket==INVALID_SOCKET)
  158.     {
  159.         AfxMessageBox("Error when socket");
  160.         return 0;
  161.     }
  162.     //设置超时
  163.     struct linger zeroLinger;
  164.     zeroLinger.l_onoff = 1;
  165.     zeroLinger.l_linger = 0;
  166.     if(setsockopt(HTTPSocket,SOL_SOCKET,SO_LINGER, (const char *)&zeroLinger, sizeof(zeroLinger))!=0)
  167.     {
  168.         closesocket(HTTPSocket);
  169.         AfxMessageBox("Error when setscokopt(LINGER)");
  170.         return 0;
  171.     }
  172.     //设置接收超时
  173.     if (setsockopt(HTTPSocket,SOL_SOCKET,SO_RCVTIMEO,(const char *)&m_nRecvTimeout,sizeof(m_nRecvTimeout))!=0)
  174.     {
  175.         closesocket(HTTPSocket);
  176.         AfxMessageBox("Error when setsockopt(RCVTIME).");
  177.         return 0;
  178.     }
  179.     //设置发送超时
  180.     if(setsockopt(HTTPSocket,SOL_SOCKET,SO_SNDTIMEO, (const char *)&m_nSendTimeout, sizeof(m_nSendTimeout))!=0)
  181.     {
  182.         closesocket(HTTPSocket);
  183.         AfxMessageBox("Error when setsockopt(SNDTIMEO).");
  184.         return 0;
  185.     }
  186.     SocketAddr.sin_addr.s_addr = htonl (INADDR_ANY);
  187.     SocketAddr.sin_family=AF_INET;
  188.     // 进行端口绑定
  189.     if (bind (HTTPSocket, (const struct sockaddr FAR *)&SocketAddr, sizeof(SocketAddr))==SOCKET_ERROR)
  190.     {
  191.         closesocket(HTTPSocket);
  192.         AfxMessageBox("Error when bind socket.");
  193.         return 0;
  194.     }
  195.     //准备连接
  196.     /// 准备连接信息
  197.     BindSocket.sin_addr.s_addr = inet_addr (strHost);
  198.     BindSocket.sin_family=AF_INET;
  199.     BindSocket.sin_port=htons(HttpPort);
  200.     struct fd_set fdSet;
  201.     struct timeval tmvTimeout={0L,0L};
  202.     FD_ZERO(&fdSet);
  203.     FD_SET(HTTPSocket, &fdSet);
  204.     if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)
  205.     {
  206.         closesocket(HTTPSocket);
  207.         AfxMessageBox("Error when select.");
  208.         return 0;
  209.     }
  210.     // 连接
  211.     if (connect(HTTPSocket, (const struct sockaddr *)&BindSocket, sizeof(BindSocket))==SOCKET_ERROR)
  212.     {
  213.         AfxMessageBox("第一次连接失败,准备第二次连接");
  214.         if (connect(HTTPSocket, (const struct sockaddr *)&BindSocket, sizeof(BindSocket))==SOCKET_ERROR)
  215.         {
  216.             closesocket(HTTPSocket);
  217.             AfxMessageBox("连接失败");
  218.             return 0;
  219.         }
  220.     }
  221.     message="连接完成/n";
  222.     return 1;
  223. }
  224. //(5)发送http请求,为下载数据进行准备
  225. int CDLAngelDlg::SendHttpHeader()
  226. {
  227.     //进行下载 
  228.     CString temp;
  229.     BOOL bReturn;
  230.     char tmpBuffer[MAXBLOCKSIZE];
  231.     ///第1行:方法,请求的路径,版本
  232.     temp="GET "+DownLoadAddress+hostFile+" HTTP/1.0/r/n";
  233.     bReturn=SocketSend(HTTPSocket,temp);
  234.     if(!bReturn)
  235.     {
  236.         message="发送请求失败";
  237.         return 0;
  238.     }
  239.     ///第2行:主机
  240.     temp="Host "+strHost+"/r/n";
  241.     bReturn=SocketSend(HTTPSocket,temp);
  242.     if(!bReturn)
  243.     {
  244.         message="发送请求失败";
  245.         return 0;
  246.     }
  247.     ///第3行:接收的数据类型
  248.     bReturn=SocketSend(HTTPSocket,"Accept: */*/r/n");
  249.     if(!bReturn)
  250.     {
  251.         message="发送请求失败";
  252.         return 0;
  253.     }
  254.     ///第4行:
  255.     temp=DownLoadAddress;
  256.     temp.Insert(0,"Referer ");
  257.     temp+="/r/n";
  258.     bReturn=SocketSend(HTTPSocket,temp);
  259.     if(!bReturn)
  260.     {
  261.         message="发送请求失败";
  262.         return 0;
  263.     }
  264.     ///第5行:浏览器类型
  265.     bReturn=SocketSend(HTTPSocket,"User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DTS Agent;)/r/n");
  266.     if(!bReturn)
  267.     {
  268.         message="发送请求失败";
  269.         return 0;
  270.     }
  271.     ///第6行:连接设置,保持
  272.     // SocketSend(HTTPSocket,"Connection:Keep-Alive/r/n");
  273.     ///第7行:Cookie.
  274.     bReturn=SocketSend(HTTPSocket,"Cache-Control: no-cache/r/n");
  275.     if(!bReturn)
  276.     {
  277.         message="发送请求失败";
  278.         return 0;
  279.     }
  280.     bReturn=SocketSend(HTTPSocket,"Proxy-Connection: Keep-Alive/r/n");
  281.     if(!bReturn)
  282.     {
  283.         message="发送请求失败";
  284.         return 0;
  285.     }
  286.     /// 续传
  287.     //Range是要下载的数据范围,对续传很重要
  288.     if(continueFlag)
  289.     {
  290.         temp.Format("Range: bytes=%d- /r/n",conLength);
  291.         bReturn=SocketSend(HTTPSocket,temp);
  292.         if(!bReturn)
  293.         {
  294.             message="发送请求失败";
  295.             return 0;
  296.         }
  297.     }
  298.     
  299.     ///最后一行:空行
  300.     bReturn=SocketSend(HTTPSocket,"/r/n");
  301.     if(!bReturn)
  302.     {
  303.         message="发送请求失败";
  304.             return 0;
  305.         }
  306.         ///取得http头
  307.         int i;
  308.         i=GetHttpHeader(HTTPSocket,tmpBuffer);
  309.         if(!i)
  310.         {
  311.             message="获取HTTP头出错";
  312.             return 0;
  313.         }
  314.         //如果取得的http头含有404等字样,则表示连接出问题
  315.         temp=tmpBuffer;
  316.         if(temp.Find("404")!=-1)
  317.         {
  318.             return 0;
  319.         }
  320.         // 得到待下载文件的大小
  321.         filelength=GetFileLength(tmpBuffer);
  322.         return 1;
  323. }
  324. //这样,就连接到网上的另一台机了,如何下载数据,不用多说了吧
  325.     while((num!=SOCKET_ERROR) && (num!=0))
  326.     {
  327.         num=recv(HTTPSocket, (char FAR *)tmpBuffer,(MAXBLOCKSIZE-1) ,0); 
  328.         file.Write(tmpBuffer,num);
  329.         if(ExitFlag)
  330.         {
  331.             file.Close();
  332.             closesocket(HTTPSocket);
  333.             DownComplete=1;
  334.             m_message.CleanText();
  335.             m_message.ShowColorText(RGB(128,128,0),DLCompleteMes);
  336.             m_progress.ShowWindow(SW_HIDE);
  337.             m_stopDownload.ShowWindow(SW_HIDE);
  338.             _endthread();
  339.         }
  340.     }
  341. }

你可能感兴趣的:(socket,tcp,Stream,浏览器,服务器,null)