注册通行证 用户名 密码
  • 文章投稿
  • 博客
  • 论坛
  • 设为首页
  • 加入收藏
jztop.com网络技术
  • 首页
  • | iT新闻
  • | 操作系统
  • | 组网建网
  • | 网络安全
  • | 程序开发
  • | 办公一族
  • | 工具软件
  • | 网页制作
  • | 多媒体制作
  • | 网吧技术
  • | 服务器
  • | 专题教程
Vista | 软件评测 | 系统备份 | 优化 | 进程 | 聊天 | 病毒 | Linux | 黑客 | 防火墙 | 数据库 | Web开发 | Java | Word | 游戏 | 32位开发 | 移动开发
当前位置:首页 > 程序开发 > 32位开发 > C/C++ 内容正文:透过代理看世界 用VC++实现http代理

透过代理看世界 用VC++实现http代理

发布时间:2006-05-05 19:03:11 来源:BLOG 网友评论 0 条

  为了帮网友些个用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();
   }

 }

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

相关文章
  • 伪随机数生成及在VC++中的实现
  • 为VC++应用程序对话框添加透明位图
  • VC++编程实现对波形数据的频谱分析
  • 用VC++模拟实现QQ密码盗窃软件
  • VC++下用MSComm控件实现串口通讯
【评论】【收藏本文】【打印】【关闭】
上一篇文章:C++箴言:只要有可能就推迟变量定义
下一篇文章:C++箴言,Terminology术语
讨论区
查看
已有 0 位对此新闻感兴趣的网友发表了看法
匿名发表
注册通行证 登陆
图文阅读推荐
推荐阅讯
  • C++ SDK+Symbian开发入门之部署
  • VC中借助DirectDraw实现水波的模拟
  • VC++下用MSComm控件实现串口通讯
  • Visual C++中调用DLL实现数据加密
  • C++的未来之路:C++0x概览
  • C++启蒙之用C++制作程序
  • 在C++语言中,关于内联函数(inline)的入门教
  • 用VC实现特定编辑框上对回车键响应
  • C++的iostream标准库介绍
  • C++中建立对象间消息连接的系统方法
阅读排行
  • 1.Borland 发布C++ Builder 2006 RAD 环境
  • 2.C/C++程序员应聘常见面试题深入剖析
  • 3.Visual C++常用数据类型转换详解
  • 4.C++中的 static 关键字
  • 5.利用VC++实现局域网实时视频传输
  • 6.浅谈C/C++内存泄漏及其检测工具
  • 7.英国投票否决C++/CLI 微软强攻ISO标准受挫
  • 8.VC++下用MSComm控件实现串口通讯
  • 9.伪随机数生成及在VC++中的实现
  • 10.VC++编程实现对波形数据的频谱分析
专题教程
  • 大话G游 专题:手机病毒揭密
  • ARP攻击防范与解决方案 路由故障处理手册
  • Picasa中文版_Picasa教程 专题:清除流氓软件
  • Firefox专题 seo搜索引擎优化专区
  • 重装Windows必知的事情 装机之必备软件大行动
病毒专杀栏
  • 杀毒软件反被病毒杀 连"救命"都不能喊
  • 金山ARP防火墙
  • 还原卡神话破灭“机器狗”病毒来势汹汹
  • cctv经济半小时:你的手机现在安全吗?
  • 新挂马方式开始流行 ARP挂马称雄局域网
  • 木马和病毒清除的通用解法
  • IP地址不再冲突 查找ARP攻击者元凶
  • 教你几招识别和防御Web网页木马
  • 分析:封杀BT只是暂时的止痛药
  • QQ爆危险漏洞,“QQ游戏邀请大盗”邀请你玩病
关于我们 | 诚聘英才 | 联系我们 | 版权声明 | 网站大事 | 网站地图 | 意见建议
CopyRight 2005-2007 Jztop.Com 版权所有 未经许可 请勿转载