主页 PC知识 网管技术 黑客帝国 安全技术 开放系统 程序设计 搜索 技术论坛

 

相关联接
 
RHU本级分类

编程语言
程序代码
WIN/*NIX编程
其他类别
JAVA专区

 
RHU阅读排行
·在LinuxShell程序中进行身份验证
·截获流经本机网卡的IP数据包
·枚举进程和杀进程的小工具
·从蓝屏最小的asp木马来看C/S木马的编写
·用tc+iptables+HTB解决ADSL宽带速度瓶颈技术
·通过 Visual C++ 的编程模型和编译器优化增强您的应用程序
·Windows管道技术简述
·利用键盘钩子开发按键发音程序
·一个Linux病毒原型分析
·XP终端服务远程登录批处理

 
 
RHU最新文章
·Webshell下破解计算机管理员密码
·打造XP下可运行的微型PE文件(292字节)
·Win32平台下的Rootkit习作
·Linux如何在系统运行过程中修改内核参数
·Shell编程:Linux系统环境程序设计之路
·汇编创建简单的窗口
·深入浅出Win32多线程程序设计之线程控制
·VC实现Win2000下屏蔽Ctrl+Alt+Del键
·隐藏任意进程 目录/文件 注册表 端口
·Windows 的多线程程序设计初步 

 
 
RHU相关搜索









 
 
RHU广而告之

 
 
>您的位置:首页 -> 程序设计 -> WIN/*NIX编程
透过代理看世界 用VC++实现http代理

作者:RHU-TAC编辑员 来自:RHU网络采集 时间:2005-8-16 双击滚屏 收藏本页 字体:


点击 查看RHU2004全年文章


为了帮网友些个用http下载动画的程序,临时在网上翻了翻,看看有没有利用http代理来下载的例子。结果,似乎很多人都愿意去转载一个有头无尾的例子,还美其名曰“我在查阅RFC文档和相关资料后,特总结一些TCP协议穿透代理服务器的程序片断,希望对大家有所帮助。”

  如果真的想帮助大家,为什么不说的详细一些?

  无奈之下,自己去翻rfc文档,找了些资料,写了这个利用http代理来下载文件的资料

  代码如下:

  (1)一些基本变量

SOCKET                                    HTTPSocket;   // 主socket
struct sockaddr_in                   SocketAddr;   // address socket
struct sockaddr_in                   BindSocket;   // for bind


int   m_nRecvTimeout;  // recieve timeout
int   m_nSendTimeout;  // send timeout

WSADATA           wsaData;

// 要下载文件部分。好像在BindSocket.sin_addr.s_addr = inet_addr (strHost);时,只能使用ip地址,所以了。。。

// 如果谁知道更好的方法,别忘了告诉我一下。

CString strHost="111.111.111.111 ";
CString DownLoadAddress="http://www.aitenshi.com/bbs/images/";
CString hostFile="logo.gif";
int HttpPort=80;


  (2)一些函数,用来取得http头,和获取文件大小

int GetFileLength(char *httpHeader)
{
        CString strHeader;
         int local;
         strHeader=(CString)httpHeader;
         local=strHeader.Find("Content-Length",0);
         local+=16;
         strHeader.Delete(0,local);
         local=strHeader.Find("\r");
         strHeader.SetAt(local,'\0');

         char temp[30];
         strcpy(temp,strHeader.GetBuffer(strHeader.GetLength()));
         return atoi(temp);
}

int GetHttpHeader(SOCKET sckDest,char *str)
{
         BOOL m_bResponsed=0;
         int m_nResponseHeaderSize;

         if(!m_bResponsed)
         {
                  char c = 0;
          int nIndex = 0;
          BOOL bEndResponse = FALSE;
          while(!bEndResponse && nIndex < 1024)
          {
                   recv(sckDest,&c,1,0);
                   str[nIndex++] = c;
                   if(nIndex >= 4)
                   {
                            if(str[nIndex - 4] == '\r' && str[nIndex - 3] == '\n'
                             && str[nIndex - 2] == '\r' && str[nIndex - 1] == '\n')
                            bEndResponse = TRUE;
                   }
          }
          m_nResponseHeaderSize = nIndex;
          m_bResponsed = TRUE;
         }
 
 return  m_nResponseHeaderSize;
 
}

  (3)用来发送的部分

void szcopy(char* dest,const char* src,int nMaxBytes)
{
         int i_cntr=0;
         while ((src[i_cntr]!='\0') || (i_cntr<nMaxBytes))
                    dest[i_cntr]=src[i_cntr++];
         dest[i_cntr]='\0';
}

BOOL SocketSend(SOCKET sckDest,const char* szHttp)
{

    char szSendHeader[MAXHEADERLENGTH];
    int iLen=strlen(szHttp);
    szcopy(szSendHeader,szHttp,iLen);
    if(send (sckDest  ,(const char FAR *)szSendHeader ,iLen ,0)==SOCKET_ERROR)
    {
               closesocket(sckDest);
               AfxMessageBox("Error when send");
                return FALSE;
    }

    return TRUE;
}

BOOL SocketSend(SOCKET sckDest,CString szHttp)
{

    int iLen=szHttp.GetLength();
    if(send (sckDest,szHttp,iLen,0)==SOCKET_ERROR)
    {
               closesocket(sckDest);
               AfxMessageBox("Error when send");
                return FALSE;
    }

    return TRUE;
}

  (4)用于连接的函数

  这里是做了一些连接用的操作,分了两种情况

  1)如果没有使用代理,则直接连到你指定的计算机

  2)如果使用了代理,则直接连到代理

BOOL CDLAngelDlg::ConnectHttp()
{

 message="正在建立连接\n";


  UpdateData(TRUE);
 if(m_combo=="HTTP")    // m_combo 一个下拉条
 {
           HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            SocketAddr.sin_addr.s_addr = inet_addr (m_ProxyAddr);
            SocketAddr.sin_family=AF_INET;
            SocketAddr.sin_port=htons(atoi(m_Port));

            struct fd_set fdSet;
            struct timeval tmvTimeout={0L,0L};
 
            FD_ZERO(&fdSet);
            FD_SET(HTTPSocket, &fdSet);
 
            if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)
            {
                       closesocket(HTTPSocket);
                       AfxMessageBox("Error when select.");
                       return 0;
            }


            if (connect(HTTPSocket, (const struct sockaddr *)&SocketAddr, sizeof(SocketAddr))==SOCKET_ERROR)
            {
                       message="\n代理连接失败\n";
                       m_message.CleanText();
                       m_message.AddText(message);
                       return 0;
            }

//  发送CONNCET请求令到代理服务器,用于和代理建立连接

//代理服务器的地址和端口放在m_ProxyAddr,m_Port 里面

            CString temp;
            char tmpBuffer[1024];
            temp.Format("CONNECT %s:%s HTTP/1.1\r\nUser-Agent: MyApp/0.1\r\n\r\n",m_ProxyAddr,m_Port);
            if(!SocketSend(HTTPSocket,temp))
            {
                       message="连接代理失败";
                       return 0;
            }

// 取得代理响应,如果连接代理成功,代理服务器将返回200 Connection established

            GetHttpHeader(HTTPSocket,tmpBuffer);
            temp=tmpBuffer;
            if(temp.Find("HTTP/1.0 200 Connection established",0)==-1)
            {
                       message="连接代理失败\n";
                       return 0;
            }

            message="代理连接完成\n";
            m_message.AddText("代理连接完成\n");
            return 1;   // ----------〉这里是应该注意的,连接到代理后,就可以返回了,不需要再连接网上的另外一台机,代理服务器会自动转发数据,所以,连接完代理就像连接到网上另外一台机一样
 }

//  这个,是为了给其他代理做准备
 else if(m_combo=="Socks4")
 {MessageBox("请注意,现在无法使用代理功能!");}
 else if(m_combo=="Socks5")
 {MessageBox("请注意,现在无法使用代理功能!");}

//  如果没有使用代理,就要连接到网上的另一台机

// 准备socket
  HTTPSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
      
 if (HTTPSocket==INVALID_SOCKET)
 {
  AfxMessageBox("Error when socket");
  return 0;
 }

//设置超时
 struct linger zeroLinger;
 zeroLinger.l_onoff = 1;
 zeroLinger.l_linger = 0;
 if(setsockopt(HTTPSocket,SOL_SOCKET,SO_LINGER
  ,(const char *)&zeroLinger
  ,sizeof(zeroLinger))!=0)
 {
            closesocket(HTTPSocket);
            AfxMessageBox("Error when setscokopt(LINGER)");
            return 0;
 }

//设置接收超时
 if(setsockopt(HTTPSocket,SOL_SOCKET,SO_RCVTIMEO
  ,(const char *)&m_nRecvTimeout
  ,sizeof(m_nRecvTimeout))!=0)
 {
            closesocket(HTTPSocket);
            AfxMessageBox("Error when setsockopt(RCVTIME).");
            return 0;
 }

//设置发送超时
 if(setsockopt(HTTPSocket,SOL_SOCKET,SO_SNDTIMEO
  ,(const char *)&m_nSendTimeout
  ,sizeof(m_nSendTimeout))!=0)
 {
            closesocket(HTTPSocket);
            AfxMessageBox("Error when setsockopt(SNDTIMEO).");
            return 0;
 }


 SocketAddr.sin_addr.s_addr = htonl (INADDR_ANY);
 SocketAddr.sin_family=AF_INET;

// 进行端口绑定
 if (bind (HTTPSocket,
  (const struct sockaddr FAR *)&SocketAddr,
  sizeof(SocketAddr))==SOCKET_ERROR)
 {
            closesocket(HTTPSocket);
            AfxMessageBox("Error when bind socket.");
            return 0;
 }

//准备连接

 /// 准备连接信息
 BindSocket.sin_addr.s_addr = inet_addr (strHost);
 BindSocket.sin_family=AF_INET;
 BindSocket.sin_port=htons(HttpPort);


 struct fd_set fdSet;
 struct timeval tmvTimeout={0L,0L};
 
 FD_ZERO(&fdSet);
 FD_SET(HTTPSocket, &fdSet);
 
 if (select(0,&fdSet,NULL,NULL,&tmvTimeout)==SOCKET_ERROR)
 {
            closesocket(HTTPSocket);
            AfxMessageBox("Error when select.");
            return 0;
 }

// 连接


 if (connect(HTTPSocket, (const struct sockaddr *)&BindSocket, sizeof(BindSocket))==SOCKET_ERROR)
 {
            AfxMessageBox("第一次连接失败,准备第二次连接");
            if (connect(HTTPSocket
            ,(const struct sockaddr *)&BindSocket
            ,sizeof(BindSocket))==SOCKET_ERROR)
            {
                       closesocket(HTTPSocket);
                       AfxMessageBox("连接失败");
                       return 0;
            }

 }

 message="连接完成\n";
 
 return 1;
}

  (5)发送http请求,为下载数据进行准备

int CDLAngelDlg::SendHttpHeader()
{
//进行下载

 CString temp;
 BOOL bReturn;
 char tmpBuffer[MAXBLOCKSIZE];


///第1行:方法,请求的路径,版本
 temp="GET "+DownLoadAddress+hostFile+" HTTP/1.0\r\n";
 bReturn=SocketSend(HTTPSocket,temp);
 if(!bReturn)
 {
  message="发送请求失败";
  return 0;
 }


///第2行:主机
 temp="Host "+strHost+"\r\n";
 bReturn=SocketSend(HTTPSocket,temp);
 if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }


///第3行:接收的数据类型
 bReturn=SocketSend(HTTPSocket,"Accept: */*\r\n");
   if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }


///第4行:
 temp=DownLoadAddress;
 temp.Insert(0,"Referer ");
 temp+="\r\n";
 bReturn=SocketSend(HTTPSocket,temp);
 if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }


///第5行:浏览器类型

 bReturn=SocketSend(HTTPSocket,"User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DTS Agent;)\r\n");
 if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }

///第6行:连接设置,保持
// SocketSend(HTTPSocket,"Connection:Keep-Alive\r\n");

///第7行:Cookie.

 bReturn=SocketSend(HTTPSocket,"Cache-Control: no-cache\r\n");
 if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }


 bReturn=SocketSend(HTTPSocket,"Proxy-Connection: Keep-Alive\r\n");
 if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }

/// 续传

Range是要下载的数据范围,对续传很重要
 if(continueFlag)
 {
            temp.Format("Range: bytes=%d- \r\n",conLength);
            bReturn=SocketSend(HTTPSocket,temp);
            if(!bReturn)
            {
             message="发送请求失败";
             return 0;
            }
 }

///最后一行:空行
 bReturn=SocketSend(HTTPSocket,"\r\n");
 if(!bReturn)
 {
            message="发送请求失败";
            return 0;
 }

///取得http头
 int i;
 i=GetHttpHeader(HTTPSocket,tmpBuffer);
 if(!i)
 {
            message="获取HTTP头出错";
            return 0;
 }

//如果取得的http头含有404等字样,则表示连接出问题
 temp=tmpBuffer;
 if(temp.Find("404")!=-1)
 {

  return 0;
 }

// 得到待下载文件的大小

 filelength=GetFileLength(tmpBuffer);

 return 1;
}

  这样,就连接到网上的另一台机了,如何下载数据,不用多说了吧

while((num!=SOCKET_ERROR) && (num!=0))
    {
       num=recv (HTTPSocket
                        ,(char FAR *)tmpBuffer
                        ,(MAXBLOCKSIZE-1)
            ,0);
   

    file.Write(tmpBuffer,num);

    if(ExitFlag)
   {
                file.Close();
                closesocket(HTTPSocket);

                DownComplete=1;

                m_message.CleanText();
                m_message.ShowColorText(RGB(128,128,0),DLCompleteMes);

                m_progress.ShowWindow(SW_HIDE);
                m_stopDownload.ShowWindow(SW_HIDE);
                _endthread();
   }

 }

  基本就是这样了,本人写程序水平也不是很高,这个程序还是可以用的。



OVER

[1] 页 RedHyphone.Union 投稿邮箱
[特别声明]:
本站文章大多搜索转载自网络中,如果侵犯了您的权利,请告之我们。本站将立即删除。
本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
查看评论】【向上滚屏】【关闭窗口】【 打印
-相关文章
  • openSUSE 11.1 Final - 正式发布
  • [视频]Opera Mini 4.2 正式版发布
  • dll注入系统进程(开源代码)
  • 认知盲区 解惑双网卡双线路DNS解析
  • FlashFXP 简体中文版 3.7.5 Build 1303 Beta[烈火]
  • -文章评论 (关闭)
    ·还没有相关的评论!

    网上大名:
    红旋风网络技术联盟 RHUTech.Union
     
    Copyright © 2000-2007 RedHyphone.Union All Rights Reserved. 红旋风联盟版权所有.皖ICP备05011033号
    中国红旋风网络技术联盟 | www.RedHyphone.net
    Mailto:Redhyphone@gamil.com