HTTP工作原理,为什么用程序的方式和用浏览器的方式,结果不一样

sscust 发布于 2014/11/03 16:08
阅读 2K+
收藏 2

初次详细地学习HTTP服务的原理,于是想通过java程序向百度发送一个HTTP请求,不知道哪出问题了,打印在控制台的内容和通过浏览器访问百度的返回的文本居然不一致,而且写得程序并没有很快停止,还一直处在运行的时间

请大家多多指正我这个菜鸟,可能是我程序写得不对,也可能是HTTP并没有理解透

程序源码

public class Http {

    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket s=new Socket("220.181.111.85", 80);
        OutputStream ops=s.getOutputStream();
        Writer osw=new OutputStreamWriter(ops);
        PrintWriter pw=new PrintWriter(osw);
        pw.println("GET / HTTP/1.1");
        pw.println("Host:220.181.111.85");
        pw.println("Content-Type:text/html");
        pw.println();//空行
        pw.flush();

        InputStream ips=s.getInputStream();
        Reader osr=new InputStreamReader(ips);
        BufferedReader br=new BufferedReader(osr);
        String str="";
        while((str=br.readLine())!=null){
            System.out.println(str);
        }
        System.out.println("shushu");
        br.close();
        pw.close();
        s.close();

    }
}


输出结果:

HTTP/1.1 200 OK
Date: Mon, 03 Nov 2014 07:54:13 GMT
Server: Apache
Cache-Control: max-age=86400
Expires: Tue, 04 Nov 2014 07:54:13 GMT
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-4b4c7d90"
Accept-Ranges: bytes
Content-Length: 81
Connection: Keep-Alive
Content-Type: text/html

<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

加载中
1
有明丶
有明丶

看到这些回答我也是醉了。这个和上述说得都没有关系……

你看看返回的内容 <meta http-equiv="refresh" content="0;url=http://www.baidu.com/"> 这个表示请求一个重定位刷新,重定位的地址是http://www.baidu.com/

百度的服务器的规则是,当时使用非 http://www.baidu.com/ 访问首页时,都会请求重定位到这个地址。这个重定位会由浏览器解析并响应,而你的程序没有这个功能(当然你也可以实现)。所有你看到浏览器里的内容和你程序不一样,因为浏览器的内容已经是http://www.baidu.com/ 这个地址的内容了。你可以注意一下浏览器的地址栏,是不是自动重定位到 http://www.baidu.com/ 了。这就是原因。

sscust
sscust
回复 @有明丶 : 学习了,谢谢
有明丶
有明丶
回复 @sscust : 也正如我说得,强制跳转到www.baidu.com 是百度服务器的行为,是他们规定的,这个无需纠结。而这个跳转和 使用Ip还是域名访问无关,你使用baidu.com访问,百度服务器也会让你跳转到www.baidu.com。这就是百度服务器的一个保证来源正确CDN的一个技巧。
有明丶
有明丶
回复 @sscust : 这个的层次不一样,DNS解析是在HTTP传递给TCP的时候进行的,而HTTP头里的Host只是用于标记用户的请求,告诉服务器用户是怎么请求到这个服务器的。
sscust
sscust
但是当我们用浏览器输入域名访问的时候,不都先解析成ip地址么?这和我直接用ip代替域名的方法有什么不同呢,用域名访问不都在请求服务器之前必须先转化成服务器IP地址吗?不管是DNS还是本地hosts文件,都得把域名换掉的
不日小鸡
回复 @有明丶 : 不用谢,这些不用你说。我跟他说的是为什么他的程序打印的内容和通过浏览器访问百度返回的文本不一样的原因,你明白?
下一页
1
N
Neilpang

Host 头要写 www.baidu.com

pw.println("Host:220.181.111.85");

改成 :

pw.println("Host:www.baidu.com");

百度会检查 host头, 防止ip访问。


sscust
sscust
是Socket和头的Host都得改,才能和浏览器的结果一样,有些想不明白啊
寂寞的原子
寂寞的原子
只有这条才是真的。。赞一个
1
杨三更
杨三更
建议LZ 抓浏览器的包看下 你的header跟浏览器的是很不一样的
0
赵开锦
赵开锦

结果其实是一样的,你打开浏览器的开发者工具,用这个IP的方式访问百度看看,就会发现浏览器也是有个跳转的

sscust
sscust
no,no,百度首页至少有“网页”、“视频”、“音乐”、“文库”、“百科”等之类的a便签
0
oxsicn
oxsicn

并没有问题 浏览器在访问220.181.111.85的时候接受到的内容是一样的

因为页面中这行html 意思是 跳转到 http://www.baidu.com/

<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">

所以浏览器会立马访问 http://www.baidu.com/ 




oxsicn
oxsicn
回复 @sscust : 你试试 设置头部 Request URL:http://www.baidu.com/
oxsicn
oxsicn
回复 @sscust : 我的猜测是百度判断你是通过什么域名进来的 然后返回页面 或者是跳转信息
sscust
sscust
但是怎么才能实现我的要求呢,把百度的首页的发给我的response对象全部打印出来呢?
0
不日小鸡
你那个IP是百度的么?换成180.97.33.108试试就知道了
0
figer1
figer1

其实只要换个IP就行了,程序里解析一下 www.baidu.com的IP,AAuto代码:

import console;
import wsock.tcp.client; 
var tcp = wsock.tcp.client() 

//取 www.baidu.com 的IP地址
var ip = wsock.getIp("www.baidu.com") 
tcp.connect(ip,80) 

sendData =/***********
GET /  HTTP/1.1
Host: www.baidu.com
Connection: close
User-Agent: Mozilla/4.0
Accept-Language: zh-CN,zh; 
Accept-Charset: GBK,utf-8;  
***********/
tcp.write( sendData + '\r\n\r\n' )

for(str,size in tcp.eachRead() ){ 
    console.log(str);
    console.more( 25 )
} 

tcp.close() 
console.pause()



0
丨丨丨

对于程序没有立刻停止的问题,有两种简单的改法:

1. pw.println("GET / HTTP/1.0"); //这里改为1.0

2. pw.println("Connection:close"); //设置Connection属性

如果是复杂的改法就读响应头,判断Content-Length的值。更麻烦点的还要处理chunked传输问题。

0
OSC首席键客
OSC首席键客

为什么不一样?因为你没有对服务器返回给你的响应进行处理,而是仅仅把返回原样输出。

浏览器是是对返回进行了处理的。

你目前得到的响应式跳转,而你没跳转。

浏览器得到响应和你的是一样的,而浏览器进行了跳转,最终结果就是你的和浏览器的不一样。

0
sscust
sscust

引用来自“淫监会主席”的评论

为什么不一样?因为你没有对服务器返回给你的响应进行处理,而是仅仅把返回原样输出。

浏览器是是对返回进行了处理的。

你目前得到的响应式跳转,而你没跳转。

浏览器得到响应和你的是一样的,而浏览器进行了跳转,最终结果就是你的和浏览器的不一样。

还是没法完全解释啊,百度有好几个服务器,220.181.111.8这个ip是我ping得到的,我是直接通过ip而不是域名来访问百度首页的,也就是说这种方式访问直接跳过了域名解析的步骤,为什么通过ip访问反而又得再次以“htttp://www.baidu.com/"来重新加载页面呢,就算是以域名的方式重新加载,不还是得解析成ip吗??另外我的程序运行下来,把首次返回的Response打印完了,close之后也就停止运行了,想不出程序停顿在那条语句了
sscust
sscust
回复 @不日小鸡 : 百度肯定有好几处服务器,ping一下只是你的主机的DNS得到最近的一个百度服务器而已,地区相差很远的话,地址是可能不同的
不日小鸡
我ping的是180.97.33.108 用socket访问得到的是HTML代码
返回顶部
顶部