网易、百度等公司面试题整理 - Go语言中文社区

网易、百度等公司面试题整理


1、n是一个奇数,求证n(n^2-1)能被24整除(网易)

n=2*k+1;那么n(n^2-1)=4*k(k+1)*(2k+1)=4*6*(1^2+...+k^2),显然能被24整除。

2、do...while和while...do有什么区别(华为)

前者先执行一遍循环体,在进行条件判断;后者先进性判断,然后根据判断结果来决定是否执行;所以前者的循环体至少执行一次。

3、两个整数集合A和B,求其交集(腾讯)

构造一个map,遍历A中的元素,插入到map中;然后遍历B中的元素,看是否在map中出现。

4、如何引用一个已经定义过的全局变量(华为)

可以引用头文件的方式,也可以使用extern关键字;两者的区别在于,如果变量出错了,那么前者将会在编译期间报错,而后者则会等到连接期间报错

5、甲乙丙丁4个人轮流顺序抽签(共4张签)。任何第一个抽中“请客”的人即请大家吃饭。假设:
A) 4张签中共有1张请客的签;
B) 4张签中共有2张请客的签;
C) 4张签中共有3张请客的签;
请问A)、B)、C)三种情况下甲乙丙丁每个人请大家吃饭的概率分别有多大?(迅雷)

A) 第一个人请客的概率 1/4;第二个人请客的概率是 3/4 * 1/3 = 1/4;第三个人请客的概率是 3/4 * 2/3 * 1/2 = 1/4;第四个人请客的概率是 3/4 * 2/3 * 1/2 * 1 = 1/4。
B) 第一个人请客的概率是 2/4 = 1/2;第二个人请客的概率是 2/4 * 2/3 = 1/3;第三个人请客的概率是 2/4 * 1/3 = 1/6;第四个人请客的概率是 0。
C) 第一个人请客的概率是 3/4;第二个人请客的概率是 1/4;第三四个人请客的概率是0。(跟自己想的出入挺大,自己少考虑了比较多的情况)


6、n个空间(其中n<1M),存放a到a+n-1的数,位置随机且数字不重复,a为正且未知。现在第一个空间的数被误设置为-1。已经知道被修改的数不是最小的。请找出被修改的数字是多少。
例如:n=6,a=2,原始的串为5, 3, 7, 6, 2, 4。现在被别人修改为-1, 3, 7, 6, 2, 4。现在希望找到5。(百度)

这个题如果能弄懂题目意图的话,貌似没什么难得;答案奉上:

由于修改的数不是最小的,所以遍历第二个空间到最后一个空间可以得到a的值。
a 到 a+n-1这 n个数的和是 total = na + (n - 1)n/2。
将第二个至最后一个空间的数累加获得 sub_total。
那么被修改的数就是 total - sub_total。(或许应该考虑相加溢出的情况,故应该采用边加边减的方式,或者整体减去a的值,在进行后续计算)

7、兄弟该如何分钱:

妈妈有2000元,要分给她的2个孩子。由哥哥先提出分钱的方式,如果弟弟同意,那么就这么分。但如果弟弟不同意,妈妈会没收1000元,由弟弟提出剩下 1000元的分钱方式,这时如果哥哥同意了,就分掉这剩下的1000元。但如果哥哥也不同意,妈妈会把剩下的1000元也拿走,然后分别只给他们每人100元。问:如果你是哥哥,你会提出什么样的分钱方式,使你有可能得到最多的钱?(最小单位1元)(IBM)

只要模仿海盗分金问题,采用从后往前推的思路就可以了,比较简单。

哥哥提出分配方案时,弟弟是否同意取决于拒绝后是否可以获得更多利益。弟弟分配时,哥哥是否同意也取决于拒绝后是否可以获得更多好处。所以采取由后向前推导的方法。如果在两次分配中弟弟和哥哥都不同意,则弟弟和哥哥各获得100元。弟弟分钱时,为保证哥哥同意,会提出哥哥101元,弟弟899元的分配方法。因为哥哥获得了比拒绝后的更多利益,所以必然会同意。哥哥分钱时,为保证弟弟同意,会提出哥哥1100元,弟弟900元的分配方法。因为弟弟获得了比拒绝后的更多利益,所以必然会同意。也就是说,最终哥哥会提出哥哥1100元,弟弟900元的分配方法。

8、在一个重男轻女的国家里,每个家庭都想生男孩,如果他们生的孩子是女孩,就再生一个,直到生下的是男孩为止。这样的国家,男女比例会是多少?(Google)

我的答案是1:1,或者说接近于1:1,;可以考虑采用数学的方法,对与一个家庭,如果说有N个小孩,则会出现如下情况:

1/2 N=1:1个男孩

1/4 N=2:1个男孩,1个女孩

1/2^n N=n:1个男孩,(n-1)个女孩

我们统计Boy(n)近似为1,Girl(n)=1-(n-1)/2^n,数学上来说当n比较大时,接近于1:1;但是现实生活中n都不是太大,并且人为流产(人工干预)等因素,造成生男生女的概率不相等,所以也就出现了性别失调。

9、随机洗牌问题;给出一种模拟方法,使得洗牌的结果比较随机;(微软)

1. for i:=1 to n do swap(a[i], a[random(1,n)]); // 凑合,但不是真正随机
2. for i:=1 to n do swap(a[i], a[random(i,n)]); // 真正的随机算法
其中,random(a,b)函数用于返回一个从a到b(包括a和b)的随机整数。
2)的时间复杂度O(n), 空间复杂度O(1);

参见:
http://hi.baidu.com/wulei407/blog/item/b6ea451b6572f9fdaf513315.html

http://hi.baidu.com/zhaolijun08/blog/item/9b4cfa944472521dd31b7043.html

10、在100w个数中找最大的前100个数(百度)

应该使用某种数据结构保存迄今最大的100个数。每读到一个新数时,将新数和保存的100个数中的最小一个相比较,如果新数更大些,则替换。这样扫描一遍100w个数也就获得了最大的100个数。
对于保存的100个数的数据结构,应该在最小复杂度的条件下满足
1)可以获得最小的数;
2)将最小数替换为另一个数后可以重新调整,使其可以满足条件1。
可见小根堆可以满足这些条件。
所以应该采用小根堆+扫描的方法。

11、正向最大匹配分词,怎么做最快?(百度)

Trie树(有待进一步研究)

12、session和cache的区别是什么?(百度)

session是针对单个连接(会话)来使用的,主要存储和连接相关的上下文信息,比如登录信息等等。
cache是应用程序级的,主要用来缓存计算结果,减轻服务器负担,并加快响应速度。

13、session和cookie的区别?

由于http是无状态的协议,所以我们需要使用cookie和session来维护服务器和客户端交互过程中的上下文信息。
cookie是存储在客户端的数据。服务器通过在http响应头,或者通过网页中的脚本在客户端中生成cookie。当客户端访问某个页面时,会把符合条件的cookie一并传送给服务器。这样服务器就可以获得以前记录的状态了。
session是存储在服务器端以sessionid作为key数据。服务器通过cookie(或者在url加入sessionid信息)将sessionid传给客户端,当客户端再次请求时,服务端就可以识别这个sessionid,并获得相应的上下文信息了

cookie 和session 的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE
4、单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K

14、疯子坐飞机问题

飞机上有100个座位,按顺序从1到100编号。有100个乘客,他们分别拿到了从1号到100号的座位,他们按号码顺序登机并应当对号入座,如果 他们发现对应号座位被别人坐了,他会在剩下空的座位随便挑一个坐。现在假如1号乘客疯了 -_-! (其他人没疯),他会在100个座位中随机坐一个座位。那么第100人正确坐自己座位的概率是多少? 注意登机是从1到100按顺序的。

假设飞机上只有两个座位,那么显然第二个人有50%的概率坐在自己的座位上。
假设飞机上只有三个座位,如果1号坐了自己的座位,则3号会坐在自己的座位上;如果1号坐了3号的座位,则3号不能坐到自己的座位上;如果1号坐了2号的座位,则对于3号来说,效果和2号应该坐到1号座位上,但他会随机坐相同,也就是等价于1号没疯,2号疯了,根据上面只有两个座位时的情况,知道这种情况下3号有50%的概率坐到自己的座位上。所以总体来说3号有50%的概率坐到自己的座位上。
.....
以此类推,可以知道当有100个座位时,100号坐到自己座位上的概率为50%

15、谁能先说出总和为100的数(迅雷)

甲乙两人,玩一个游戏。每人轮流说出1-10的一个数字,从甲开始。轮到某个人,使得所有说出的数字的总和等于100,就算谁赢。
请问甲或乙谁有必胜的把握,为什么?

先假设X必胜,Y必输。
那么不论Y最后说出的数字是1还是10,X都能说出一个数使得总数为100。可以推出Y最后一次说之前的总和为89。
同理可以推出Y倒数第二次说之前总和为78。
依次类推,可以知道Y说之前的数字分别为1,12,23 ... 78, 89。
可以看出X就是甲。他的策略就是,先说出1,然后乙说出数字n,甲就说11-n

16、将query按照出现的频度排序(10个1G大小的文件)(百度)
有10个文件,每个文件1G,每个文件的每一行都存放的是用户的query,每个文件的query都可能重复。如何按照query的频度排序?

1)读取10个文件,按照hash(query)%10的结果将query写到对应的文件中。
这样我们就有了10个大小约为1G的文件。任意一个query只会出现在某个文件中。
2)对于1)中获得的10个文件,分别进行如下操作
- 利用hash_map(query,query_count)来统计每个query出现的次数。
- 利用堆排序算法对query按照出现次数进行排序。
- 将排序好的query输出的文件中。
这样我们就获得了10个文件,每个文件中都是按频率排序好的query。
3)对2)中获得的10个文件进行归并排序,并将最终结果输出到文件中。
注:如果内存比较小,在第1)步中可以增加文件数。

17、有1到10w这10w个数,去除2个并打乱次序,如何找出那两个数?(腾讯)

申请10w个bit的空间,每个bit代表一个数字是否出现过。
开始时将这10w个bit都初始化为0,表示所有数字都没有出现过。
然后依次读入已经打乱循序的数字,并将对应的bit设为1。
当处理完所有数字后,根据为0的bit得出没有出现的数字。

18、在1亿条用户记录里,如何快速查询统计出看了5个电影以上的用户?(迅雷)

构建一个hash map,key为用户名,value为已经看过的电影数量。
遍历所有用户记录,然后根据用户名和已经看过电影数量的情况进行处理:
- 如果用户名不在hash map中,则添加对应用户名,并将值设为1。
- 如果用户名对应的值小于5,则将值加1。如果加1后值为5,则输出此用户名。
- 如果用户名对应的值等于5,则不进行任何操作。

19、如果在高速公路上30分钟内看到一辆车开过的几率是0.95,那么在10分钟内看到一辆车开过的几率是多少?(假设为常概率条件下)(Google)

假设10分钟内看到一辆车开过的概率是x,那么没有看到车开过的概率就是1-x,30分钟没有看到车开过的概率是(1-x)^3,也就是0.05。所以得到方程
(1-x)^3 = 0.05 解方程得到x大约是0.63

20、有25匹马,每次比赛只能有5匹马参加,问最少进行几次比赛才可以得到25匹马中跑得最快的前3名?(Google)

最少需要7次。
首先将马分成a,b,c,d,e 5个组,每组5匹,每组单独比赛。然后将每组的第一名放在一起比赛。假设结果如下
a0,a1,a2,a3,a4
b0,b1,b2,b3,b4
c0,c1,c2,c3,c4
d0,d1,d2,d3,d4
e0,e1,e2,e3,e4
其中a, b,c,d,e小组都是按照名次排列(速度a0>a1>a2>a3>a4, b0>b1....)。并第6次比赛的结果为a0>b0>c0>d0>e0。
那么第6次比赛结束后,我们知道最快的一匹为a0。
我们知道第2名的马一定是a1或者b0,所以在接下来的比赛中要包含这两匹马。如果a1快,那么第3名是a2或者b0,如果b0快,那么第3名是a1,b1或者c0。也就是说第2名和第3名一定在a1,a2,b0,b1和c0当中,所以在第7场比赛中包括这5匹马就可以得到第2名和第3名。
所以7次比赛就可以获得前3名的马。

21、根据上排给出十个数,在其下排填出对应的十个数, 要求下排每个数都是上排对应位置的数在下排出现的次数。上排的数:0,1,2,3,4,5,6,7,8,9。(腾讯)

0,1,2,3,4,5,6,7,8,9
6,2,1,0,0,0,1,0,0,0

22、ibm面试题:只有三只酒杯,如何将酒平均分给4个人喝?(IBM)

总共16两酒,4个人喝,平均每人喝4两。
假设下面的三个数是8两,8两和4两酒杯中的酒。
8 8 0
8 5 3
第一个人先喝3两,变成
8 5 0
8 2 3
第二个人先喝2两,变成
8 0 3
8 3 0
5 3 3
5 6 0
2 6 3
2 8 1
第一个人再喝1两,就刚刚喝了4两,变成
2 8 0
0 8 2
0 7 3
3 7 0
3 4 3
6 4 0
6 1 3
第三个人先喝1两,变成
6 0 3
8 0 1
第四个人先喝1两,变成
8 0 0
5 0 3
第三个人再喝3两,就刚刚喝了4两,变成
5 0 0
2 0 3
第二个人再喝2两,就刚刚喝了4两,变成
0 0 3
第四个人再喝3两,就刚刚喝了4两

23、16个硬币,A和B轮流拿走一些,每次拿走的个数只能是1,2,4中的一个数。谁最后拿硬币谁输。
问:A或B有无策略保证自己赢?

B可以保证自己赢。
如果A拿1个,则B拿2个;如果A拿2个,则B拿1个;如果A拿4个,则B拿2个。这样每次AB加起来都是3或者6,所以最后会剩下1个或4个。如果是1个则A直接输了;如果剩下4个,A全拿则输了,如果不全拿,B继续采取上面的策略,最后还是剩下1个,还是A输。

24、网易面试题:警长,逃犯和黑白帽的问题

有一位警长,抓了三个逃犯。现警长决定给他们一次机会。他拿出3顶黑帽子,两顶白帽子,然后往这三个逃犯头上每人戴了一顶帽子,每个逃犯只能看到另外两个逃犯帽子的颜色,不能看到自己帽子的颜色,而且不能进行通讯,不能进行讨论,只能靠自己的推理推出来,如果猜出来了,放一条生路,否则处死。
警长先问第一逃犯,结果第一逃犯猜错了,被杀掉了。
警长问第二个逃犯,结果还是猜错了,同样被杀掉了。
警长再问第三个逃犯,结果第三个逃犯猜对了。
说明一下,每个逃犯在回答问题时,其他逃犯是听不到的。
为什么第三个一定能猜中,请你给出解释。

如果第二个和第三个人都是白帽子,则第一个人肯定可以知道自己是黑帽子。第一个人没有猜对,说明第二和第三个人中肯定有黑帽子。
如果第三个人是白帽子,由于第二和第三个中肯定有黑帽子,那么第二个人肯定是黑帽子。第二个人没有猜对,说明第三个人不是白帽子。
所以第三个人知道自己肯定是黑帽子。

25、海量日志数据,提取出某日访问百度次数最多的那个IP。

IP地址最多有2^32=4G种取值可能,所以不能完全加载到内存中。
可以考虑分而治之的策略,按照IP地址的hash(IP)%1024值,将海量日志存储到1024个小文件中。每个小文件最多包含4M个IP地址。
对于每个小文件,可以构建一个IP作为key,出现次数作为value的hash_map,并记录当前出现次数最多的1个IP地址。
有了1024个小文件中的出现次数最多的IP,我们就可以轻松得到总体上出现次数最多的IP。

26、给40亿个不重复的unsigned int的整数,没排过序的,然后再给几个数,如何快速判断这几个数是否在那40亿个数当中?

unsigned int 的取值范围是0到2^32-1。我们可以申请连续的2^32/8=512M的内存,用每一个bit对应一个unsigned int数字。首先将512M内存都初始化为0,然后每处理一个数字就将其对应的bit设置为1。当需要查询时,直接找到对应bit,看其值是0还是1即可。

27、排序数组中,找出给定数字的出现次数;(微软)

使用二分查找的方法分别找出给定数字的开始和结束位置,最坏情况下时间复杂度为O(logn)。
方法比较直接,不过代码写起来还有些难度。有兴趣的xdjm可以练习一下 :-)

28、给定字符串,删除开始和结尾处的空格,并将中间的多个连续的空格合并成一个。
比如 “ I like http://hi.baidu.com/mianshiti ” 会变成 "I like http://hi.baidu.com/mianshiti"。

void RemoveExtraSpace(char* str) {
bool keep_space = false;
int new_str_end = 0;

for (int i = 0; str[i]; ++i) {
if (str[i] != " ") {
str[new_str_end++] = str[i];
keep_space = true;
} else if (keep_space) {
str[new_str_end++] = str[i];
keep_space = false;
}
}

if (new_str_end > 0 && str[new_str_end - 1] == " ") {
str[new_str_end - 1] = '';
} else {
str[new_str_end] = '';
}
}
29、微软面试题:正则表达式提取链接地址
写出正则表达式,从一个字符串中提取链接地址。比如下面字符串中
"IT面试题博客中包含很多 <a href=http://hi.baidu.com/mianshiti/blog/category/微软面试题> 微软面试题 </a> "
则需要提取的地址为 " http://hi.baidu.com/mianshiti/blog/category/微软面试题 "
在python中:

import re
p = re.compile('<a(?: [^>]*)+href=([^ >]*)(?: [^>]*)*>')
content = "IT面试题博客中包含很多 <a href=http://hi.baidu.com/mianshiti/blog/category/微软面试题> 微软面试题 </a> "
p.search(content).groups()

这段代码对于给出的例子是足够了,但实际情况中还需要考虑链接地址两边的单引号或者双引号,href的大小写,情况会稍微复杂些。

另外,如果面试者对正则表达式完全没有概念,可以和面试官申请换一道题,一般不会有太大影响。

参考资料:
http://wiki.ubuntu.org.cn/Python正则表达式操作指南

30、从输入URL到显示网页,后台发生了什么?

作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等。

本文将更深入的研究当你输入一个网址的时候,后台到底发生了一件件什么样的事~

1. 首先嘛,你得在浏览器里输入要网址:

image

2. 浏览器查找域名的IP地址

image

导航的第一步是通过访问的域名找出其IP地址。DNS查找过程如下:

  • 浏览器缓存 – 浏览器会缓存DNS记录一段时间。 有趣的是,操作系统没有告诉浏览器储存DNS记录的时间,这样不同浏览器会储存个自固定的一个时间(2分钟到30分钟不等)。
  • 系统缓存 – 如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用(windows里是gethostbyname)。这样便可获得系统缓存中的记录。
  • 路由器缓存 – 接着,前面的查询请求发向路由器,它一般会有自己的DNS缓存。
  • ISP DNS 缓存 – 接下来要check的就是ISP缓存DNS的服务器。在这一般都能找到相应的缓存记录。
  • 递归搜索 – 你的ISP的DNS服务器从跟域名服务器开始进行递归搜索,从.com顶级域名服务器到Facebook的域名服务器。一般DNS服务器的缓存中会有.com域名服务器中的域名,所以到顶级服务器的匹配过程不是那么必要了。

DNS递归查找如下图所示:

500px-An_example_of_theoretical_DNS_recursion_svg

DNS有一点令人担忧,这就是像wikipedia.org 或者 facebook.com这样的整个域名看上去只是对应一个单独的IP地址。还好,有几种方法可以消除这个瓶颈:

  • 循环 DNS 是DNS查找时返回多个IP时的解决方案。举例来说,Facebook.com实际上就对应了四个IP地址。
  • 负载平衡器 是以一个特定IP地址进行侦听并将网络请求转发到集群服务器上的硬件设备。 一些大型的站点一般都会使用这种昂贵的高性能负载平衡器。
  • 地理 DNS 根据用户所处的地理位置,通过把域名映射到多个不同的IP地址提高可扩展性。这样不同的服务器不能够更新同步状态,但映射静态内容的话非常好。
  • Anycast 是一个IP地址映射多个物理主机的路由技术。 美中不足,Anycast与TCP协议适应的不是很好,所以很少应用在那些方案中。

大多数DNS服务器使用Anycast来获得高效低延迟的DNS查找。

3. 浏览器给web服务器发送一个HTTP请求

image

因为像Facebook主页这样的动态页面,打开后在浏览器缓存中很快甚至马上就会过期,毫无疑问他们不能从中读取。

所以,浏览器将把一下请求发送到Facebook所在的服务器:

GET http://facebook.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...]
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...]
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: facebook.com
Cookie: datr=1265876274-[...]; locale=en_US; lsd=WW[...]; c_user=2101[...]

GET 这个请求定义了要读取的URL: “http://facebook.com/”。 浏览器自身定义 (User-Agent 头), 和它希望接受什么类型的相应 (Accept and Accept-Encoding 头). Connection头要求服务器为了后边的请求不要关闭TCP连接。

请求中也包含浏览器存储的该域名的cookies。可能你已经知道,在不同页面请求当中,cookies是与跟踪一个网站状态相匹配的键值。这样cookies会存储登录用户名,服务器分配的密码和一些用户设置等。Cookies会以文本文档形式存储在客户机里,每次请求时发送给服务器。

用来看原始HTTP请求及其相应的工具很多。作者比较喜欢使用fiddler,当然也有像FireBug这样其他的工具。这些软件在网站优化时会帮上很大忙。

除了获取请求,还有一种是发送请求,它常在提交表单用到。发送请求通过URL传递其参数(e.g.: http://robozzle.com/puzzle.aspx?id=85)。发送请求在请求正文头之后发送其参数。

像“http://facebook.com/”中的斜杠是至关重要的。这种情况下,浏览器能安全的添加斜杠。而像“http: //example.com/folderOrFile”这样的地址,因为浏览器不清楚folderOrFile到底是文件夹还是文件,所以不能自动添加 斜杠。这时,浏览器就不加斜杠直接访问地址,服务器会响应一个重定向,结果造成一次不必要的握手。 

4. facebook服务的永久重定向响应

image

图中所示为Facebook服务器发回给浏览器的响应:

HTTP/1.1 301 Moved Permanently
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Location: http://www.facebook.com/
P3P: CP="DSP LAW"
Pragma: no-cache
Set-Cookie: made_write_conn=deleted; expires=Thu, 12-Feb-2009 05:09:50 GMT;
path=/; domain=.facebook.com; httponly
Content-Type: text/html; charset=utf-8
X-Cnection: close
Date: Fri, 12 Feb 2010 05:09:51 GMT
Content-Length: 0

服务器给浏览器响应一个301永久重定向响应,这样浏览器就会访问“http://www.facebook.com/” 而非“http://facebook.com/”。

为什么服务器一定要重定向而不是直接发会用户想看的网页内容呢?这个问题有好多有意思的答案。

其中一个原因跟搜索引擎排名有 关。你看,如果一个页面有两个地址,就像http://www.igoro.com/ 和http://igoro.com/,搜索引擎会认为它们是两个网站,结果造成每一个的搜索链接都减少从而降低排名。而搜索引擎知道301永久重定向是 什么意思,这样就会把访问带www的和不带www的地址归到同一个网站排名下。

还有一个是用不同的地址会造成缓存友好性变差。当一个页面有好几个名字时,它可能会在缓存里出现好几次。

5. 浏览器跟踪重定向地址

image

现在,浏览器知道了“http://www.facebook.com/”才是要访问的正确地址,所以它会发送另一个获取请求:

GET http://www.facebook.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, [...]
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; [...]
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cookie: lsd=XW[...]; c_user=21[...]; x-referer=[...]
Host: www.facebook.com

头信息以之前请求中的意义相同。

6. 服务器“处理”请求

image

服务器接收到获取请求,然后处理并返回一个响应。

这表面上看起来是一个顺向的任务,但其实这中间发生了很多有意思的东西- 就像作者博客这样简单的网站,何况像facebook那样访问量大的网站呢!

  • Web 服务器软件
    web服务器软件(像IIS和阿帕奇)接收到HTTP请求,然后确定执行什么请求处理来处理它。请求处理就是一个能够读懂请求并且能生成HTML来进行响应的程序(像ASP.NET,PHP,RUBY...)。

    举 个最简单的例子,需求处理可以以映射网站地址结构的文件层次存储。像http://example.com/folder1/page1.aspx这个地 址会映射/httpdocs/folder1/page1.aspx这个文件。web服务器软件可以设置成为地址人工的对应请求处理,这样 page1.aspx的发布地址就可以是http://example.com/folder1/page1。

  • 请求处理
    请求处理阅读请求及它的参数和cookies。它会读取也可能更新一些数据,并讲数据存储在服务器上。然后,需求处理会生成一个HTML响应。

所 有动态网站都面临一个有意思的难点 -如何存储数据。小网站一半都会有一个SQL数据库来存储数据,存储大量数据和/或访问量大的网站不得不找一些办法把数据库分配到多台机器上。解决方案 有:sharding (基于主键值讲数据表分散到多个数据库中),复制,利用弱语义一致性的简化数据库。

委 托工作给批处理是一个廉价保持数据更新的技术。举例来讲,Fackbook得及时更新新闻feed,但数据支持下的“你可能认识的人”功能只需要每晚更新 (作者猜测是这样的,改功能如何完善不得而知)。批处理作业更新会导致一些不太重要的数据陈旧,但能使数据更新耕作更快更简洁。

7. 服务器发回一个HTML响应

image

图中为服务器生成并返回的响应:

HTTP/1.1 200 OK
Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0,
pre-check=0
Expires: Sat, 01 Jan 2000 00:00:00 GMT
P3P: CP="DSP LAW"
Pragma: no-cache
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
X-Cnection: close
Transfer-Encoding: chunked
Date: Fri, 12 Feb 2010 09:05:55 GMT

2b3Tn@[...]

整个响应大小为35kB,其中大部分在整理后以blob类型传输。

内容编码头告诉浏览器整个响应体用gzip算法进行压缩。解压blob块后,你可以看到如下期望的HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"    
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en" id="facebook" class=" no_js">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-language" content="en" />
...

关于压缩,头信息说明了是否缓存这个页面,如果缓存的话如何去做,有什么cookies要去设置(前面这个响应里没有这点)和隐私信息等等。

请注意报头中把Content-type设置为“text/html”。报头让浏览器将该响应内容以HTML形式呈现,而不是以文件形式下载它。浏览器会根据报头信息决定如何解释该响应,不过同时也会考虑像URL扩展内容等其他因素。

8. 浏览器开始显示HTML

在浏览器没有完整接受全部HTML文档时,它就已经开始显示这个页面了:

image

9. 浏览器发送获取嵌入在HTML中的对象

image

在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。

下面是几个我们访问facebook.com时需要重获取的几个URL:

    版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
    原文链接:https://blog.csdn.net/iamfranter/article/details/6828957
    站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-31 13:18:27
  • 阅读 ( 2585 )
  • 分类:面试题

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢