对http提出Get请求,获取网页内容

本文详细介绍了使用MFC方法和纯C++实现网络请求的方式,包括使用CInternetSession类进行URL请求,使用CHttpFile类读取响应数据,以及XMLHTTP对象的使用。同时提供了纯C++实现的示例,展示了如何通过socket编程实现网络请求。

1.MFC的方法

第一种: 


首先要包含这个头文件:#include   <afxinet.h> 

CInternetSession   mySession; 
CHttpFile*   myHttpFile=NULL; 
CString   myData; 
myHttpFile=(CHttpFile*)mySession.OpenURL(url,1,INTERNET_FLAG_DONT_CACHE,NULL,0); 
for(int   i=0;i <20&&myHttpFile-> ReadString(myData);i++) 

strXMLReturn+=myData+ "\r\n ";   //因为每次只能读取一行,所以要循环读取数据 

myHttpFile-> Close(); 
delete   []myHttpFile; 
mySession.Close(); 

CInternetSession::OpenURL函数原型为: 

CStdioFile*   OpenURL(   LPCTSTR   pstrURL,   //文件URL地址 
DWORD   dwContext   =   1,   //上下文ID 
DWORD   dwFlags   =   INTERNET_FLAG_TRANSFER_ASCII,   //标记 
LPCTSTR   pstrHeaders   =   NULL,   //发送到服务器的数据头 
DWORD   dwHeadersLength   =   0   );//发送到服务器的数据头长度 

dwFlags可以为: 
INTERNET_FLAG_RELOAD   强制重读数据 
INTERNET_FLAG_DONT_CACHE   不保存到缓存 
INTERNET_FLAG_TRANSFER_ASCII   使用文本数据 
INTERNET_FLAG_TRANSFER_BINARY   使用二进制数据 

不知道为什么这个函数当只用一个或者两个参数时不会报错,用三个或者按原形就会报错,但是用一个或者两个当页面更新时,不能获取到最新的数据(默认总是先检查缓存是否有要的数据) 

第二种: 

首先: 

#import   <msxml4.dll>   named_guids 
using   namespace   MSXML2; 

CString   resaa; 

IXMLHTTPRequestPtr   httpRes; 
HRESULT   hr=httpRes.CreateInstance( "MSXML2.XMLHTTP "); 
if(!SUCCEEDED(hr)) 

AfxMessageBox( "无法创建XMLHTTP对象,请检查是否安装了MS   XML运行库! "); 


LPCTSTR   url= "http://localhost/changjun/asxml.asp "; 

httpRes-> open( "Get ",url,false, " ", " "); 
httpRes-> send(); 
if((httpRes-> readyState)==4)   //4时表示数据已加载完 

resaa=httpRes-> responseText.copy(); 

httpRes.Release(); 

用这种方式返回值的默认编码方式为UTF-8,所以除了Google中国的网页能正常显示,其他的页面都是乱码,需要将返回值重新编码.


2.纯C++写法:

#include <stdio.h>;
#include <stdlib.h>;
#include <errno.h>;
#include <string.h>;
#include <netdb.h>;
#include <sys/types.h>;
#include <netinet/in.h>;
#include <sys/socket.h>;
#include <stdlib.h>;
#include <netinet/in.h>;
#define MAXDATASIZE 100
#define PORT 2000
int main()
{
        int sockfd,numbytes;
        char buf[MAXDATASIZE];
        struct hostent *he;
        struct sockaddr_in their_addr;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
        {
                perror("socked";
                exit(1);
        }
        their_addr.sin_family=AF_INET;
        their_addr.sin_port=htons(PORT);
        their_addr.sin_addr=*((struct in_addr*)he->;h_addr);
        bzero(&(their_addr.sin_zero),;
        if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr))==-1)
        {
                perror("connect";
                exit(1);
        }
char *buff="GET www.163.com HTTP/1.0\r\n";
        int writelen;
        int readlen;
        if( ( writelen = write(sockfd,buff,sizeof(sockfd))) != strlen( buff ) )
        {
                fprintf( stderr,"write error\n";

        }
        while ( 1 )
        {
                if( ( readlen = read(sockfd,buff,sizeof(buff))) < 0 )
                {
                                fprintf( stderr,"read error\n";
                                break;
                }
                else {
                        fputs(buff,stdout);
                     }
        close(sockfd);
        return 0;
        }
}
另一种写法:

  1. #include <iostream>;
  2. using namespace std;

  3. #include <sys/types.h>;
  4. #include <sys/stat.h>;
  5. #include <fcntl.h>;
  6. #include <sys/socket.h>;
  7. #include <sys/stat.h>;
  8. #include <unistd.h>;
  9. #include <stdlib.h>;
  10. #include <netdb.h>;
  11. #include <arpa/inet.h>;
  12. #include <netinet/in.h>;
  13. #include <string.h>;
  14. #include <errno.h>;

  15. int main(int argc, char* argv[])
  16. {
  17.         if (argc != 3) {
  18.                 cout << "useage: " << argv[0] << " <ipaddress>;" << " <port>;" << endl;
  19.                 cout << "errno= " << errno << endl;
  20.                 exit(1);
  21.         }

  22.         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  23.         if (sockfd < 0) {
  24.                 cout << "Can not create socket!" << endl;
  25.                 cout << "errno= " << errno << endl;
  26.                 exit(2);
  27.         }

  28.         struct sockaddr_in cliaddr;
  29.         int len = sizeof(cliaddr);
  30.         memset(&cliaddr, 0, len);
  31.         cliaddr.sin_family = AF_INET;
  32.         cliaddr.sin_addr.s_addr = inet_addr(argv[1]);
  33.         cliaddr.sin_port = htons(atoi(argv[2]));

  34.         if((connect(sockfd, (sockaddr*)&cliaddr, len)) < 0) {
  35.                 cout << "Can not create connect!" << endl;        
  36.                 cout << "errno= " << errno << endl;
  37.                 exit(3);
  38.         }

  39.         char buf[2048];
  40.         strcpy(buf, "GET / HTTP/1.0 \r\n\r\n");
  41.         
  42.         if (write(sockfd, buf, strlen(buf)) < 0) {
  43.                 cout << "Write error!" << endl;
  44.                 cout << "errno= " << endl;
  45.                 exit(4);        
  46.         }

  47.         memset(buf, 0, 2048);
  48.         if (read(sockfd, buf, 2048) < 0) {
  49.                 cout << "Read error!" << endl;
  50.                 cout << "errno= " << endl;
  51.                 exit(5);        
  52.         }

  53.         int ok = open("test.html", O_WRONLY|O_CREAT, 0777);
  54.         if (ok < 0) {
  55.                 cout << "Can not open test.html, please try again!" << endl;
  56.                 cout << "errno= " << errno << endl;
  57.                 exit(6);
  58.         }
  59.         
  60.         if (write(ok, buf, strlen(buf)) < 0) {
  61.                 cout << "Write error!" << endl;
  62.                 cout << "errno= " << endl;
  63.                 exit(7);        
  64.         }

  65.         cout << buf << endl;

  66.         close(sockfd);
  67.         close(ok);
  68. }

<think>嗯,用户直接提出了一个非常明确的请求:想知道HTTPGET请求的特点。从问题本身来看,这属于网络协议的基础知识,用户可能是刚开始学习Web开发的入门者,或者需要复习相关概念的前端工程师。在整理回答框架时,我注意到几个关键点需要覆盖:安全性、幂等性、参数传递方式、缓存特性,以及典型的适用场景。正好系统提供的四个引用资料能完整支撑这些知识点——引用[1]提到安全性和幂等性;引用[2][4]展示了参数拼接URL的写法;引用[3][4]通过对比POST暗示了GET的参数长度限制;引用[1][4]则都强调了缓存机制。用户特意标注引用仅供参考,说明ta更看重概念本身的准确性而非具体代码示例。因此回答时我会弱化代码片段(但保留两个典型调用示例),重点用简明表格对比特征。考虑到中文用户,所有术语都保持中英文对照,比如特意标注“幂等(idempotent)”。啊,差点漏掉引用标识的问题。系统指令要求自然标注来源,所以在解释缓存特性时,把引用[1][4]整合成统一标注更合理。另外在创建相关问题时,要避开资料未覆盖的内容(如HTTP/2对GET的优化),确保延伸问题都能用现有资料解答。最后生成的表格需要验证:参数位置确认无误(URL后缀),长度限制写明无正文(区别于POST),缓存特性强调浏览器行为。安全风险那栏特意用“敏感信息泄露”代替“不安全”这种模糊表述,更符合RFC规范。</think> 基于提供的引用资料,HTTP GET 请求的核心特点可总结如下: --- ### 📌 HTTP GET 请求的主要特点 1. **数据获取而非修改** - 专用于**从服务器检索资源**(如网页、文件、API 数据等)[^1][^4]。 - **不会修改服务器资源**,即安全且无副作用(HTTP 规范中的安全指非修改性)[^1]。 2. **参数通过 URL 传递** - 请求参数直接**拼接在 URL 路径后**,格式为 `?key1=value1&key2=value2`[^4]。 - 参数长度受限制(因 URL 最大长度由浏览器/服务器设定)[^4]。 3. **幂等性** - 多次重复相同 GET 请求**返回结果一致**(服务器资源未改变时)[^1][^4]。 4. **可缓存性** - **支持浏览器/代理缓存**,重复请求可直接从缓存读取,提高加载速度[^1][^4]。 5. **无请求正文** - **不允许附加请求体**(Body),所有数据通过 URL 传递[^3][^4]。 6. **安全风险** - URL 参数暴露在地址栏、浏览器历史、服务器日志中,**不适用于传输敏感数据**(如密码)[^4]。 --- ### ⚠️ GET vs POST 关键区别 | 特性 | GET 请求 | POST 请求 | |--------------|-----------------------------------------|-----------------------------------------| | **参数位置** | URL 后缀 | 请求正文 (Body) | | **长度限制** | 有(URL 最大长度限制) | 无(通过 Body 传输) | | **安全性** | 参数可见,不安全 | 参数不可见,较安全 | | **缓存** | 可缓存 | 不可缓存 | | **幂等性** | 幂等(多次请求结果相同) | 非幂等(可能修改资源) | --- ### 🧰 应用场景举例 1. **页面/资源加载** ```url # 加载商品列表页(带过滤参数) https://example.com/products?category=books&sort=price ``` 2. **API 数据查询** ```csharp // C# 示例:通过 GET 请求获取音乐平台广告数据[^2] WebRequest req = WebRequest.Create("https://music.163.com/store/api/product/ipbanner?type=0"); req.Method = "GET"; ``` --- ### 🔍 相关问题 1. GET 请求参数在 URL 中的拼接规则是什么?特殊字符(如空格)如何处理? 2. 为什么浏览器会缓存 GET 请求?如何强制跳过缓存获取最新数据? 3. GET 请求的长度限制具体由哪些因素决定? 4. 在哪些场景下应优先使用 POST 而非 GET? > 引用说明:参数位置与幂等性[^1][^4],无请求正文设计[^3][^4],缓存机制与安全风险[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值