经常面试被问到什么是http协议,什么是TCP协议,而且每次都弄不清楚,是时候记录一下了
如果读者对计算机网络的体系结构比较了解的话应该清楚,IP协议位于网络层,TCP/UDP协议位于传输层,HTTP位于应用层,如下图:
说明:
其实发起一个HTTP请求就是建立一个socket连接,是不过HTTP请求是无状态且短链接的协议
浏览器在建立socket连接之前,先根据DNS服务器去把域名解析成对应的IP地址,将IP地址和默认的80端口(https请求和http类似,只不过他用的是443端口和证书)与服务器建立一个socket链接。
我们利用代码来模拟一下客户端的请求过程,具体代码:
URLConnection urlConnection = new URL("").openConnection();t();Map<String, List<String>> map = HeaderFields();for(String key:map.keySet()){System.out.println(key+":"(key));}
深入分析URLConnection代码发现,它的底层也是使用socket实现,sun.NetworkClient的内部实现:
protected Socket doConnect (String server, int port)152 throws IOException, UnknownHostException {153 Socket s;154 if (proxy != null) {155 if (pe() == Proxy.Type.SOCKS) {156 s = AccessController.doPrivileged(157 new PrivilegedAction<Socket>() {158 public Socket run() {159 return new Socket(proxy);160 }});161 } else if (pe() == Proxy.Type.DIRECT) {162 s = createSocket();163 } else {164 // Still connecting through a proxy165 // server & port will be the proxy address and port166 s = new Socket(Proxy.NO_PROXY);167 }168 } else169 s = createSocket();170 // Instance specific timeouts do have priority, that means171 // connectTimeout & readTimeout (-1 means not set)172 // Then global default timeouts173 // Then no timeout.174 if (connectTimeout >= 0) {175 s.connect(new InetSocketAddress(server, port), connectTimeout);176 } else {177 if (defaultConnectTimeout > 0) {178 s.connect(new InetSocketAddress(server, port), defaultConnectTimeout);179 } else {180 s.connect(new InetSocketAddress(server, port));181 }182 }183 if (readTimeout >= 0)184 s.setSoTimeout(readTimeout);185 else if (defaultSoTimeout > 0) {186 s.setSoTimeout(defaultSoTimeout);187 }188 return s;189 }190
我们也可以通过curl/charles/wireshark来进行抓包分析HTTP数据包,下面我通过curl来查看http的请求头信息,命令如下:
HTTP 请求由三部分组成:请求行、 请求头和请求正文。
curl -v
请求头信息:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6
Cache-Control:max-age=0
Connection:keep-alive
Cookie:BIDUPSID=FAB2DD0A535CCE85F60B0E747EDD2F80; PSTM=1493346210; BAIDUID=A132C53C54C0BD857558B3C9A0BE6888:FG=1; BDUSS=VxWWlZN2p3Z3I5a3hyejdvQ0ppVmxXcmNDcFhyckozT2t4RE5HRXRxall6UzlaSVFBQUFBJCQAAAAAAAAAAAEAAAAkHEsRenp4MDEwMTAxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANhACFnYQAhZMX; BDSFRCVID=krPsJeC62xGbH8QZbUZhu8KOK2KfnEnTH6aomPIViliOVFyXv0lyEG0PqU8g0Kub5QsaogKK0mOTHvbP; H_BDCLCKID_SF=tb4q_I_aJCvbfP0kj502e5OQDa0jJI62aKDs0U5c-hcqEIL4jh85jIuuWmcPBUoaJnI8-bCa2R6RMxbSj4Qo3-INyx6UKf7bWnvnWnTCyp5nhMJI3j7JDMP0qtOkKxny523ion6vQpn-8UtuD6-bDj5WeHDs-bbfHjrtBRRV-bnHDR365DTjhPrMMp5TbMT-0bFHXp3tWInGoRoaW47heMPgyN5iKt64aHn7_JjOaxJzSRT1Mfn4QRFR5G3QhxQxtNRD-CnjtpvhHC5hKPQobUPUDMc9LUvqKH4E3-oJqCKhMDLm3H; BDRCVFR[S4-dAuiWMmn]=I67x6TjHwwYf0; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BD_CK_SAM=1; PSINO=2; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BD_HOME=1; H_PS_PSSID=1441_19033_21111_17001_19897_21670_22582; BD_UPN=123253; sugstore=1
Host:www.baidu
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
常见请求头
GET
方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。Host
(发送请求时,该报头域是必需的)
Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。
Accept
:浏览器可以接受的媒体类型(MIME类型),
例如: Accept: text/html 代表浏览器可以接受服务器回发的类型为 text/html 也就是我们常说的html文档, 如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)。
通配符 * 代表任意类型。例如 Accept: / 代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)
User-Agent
:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.
我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上, 服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器
Accept-Encoding
:浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码);
例如: Accept-Encoding: gzip, deflate。Server能够向支持gzip/deflate的浏览器返回经gzip或者deflate编码的HTML页面。 许多情形下这可以减少5到10倍的下载时间,也节省带宽。
Accept-Language
: 浏览器申明自己接收的语言。
语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等;
例如: Accept-Language:zh-cn 。如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。
Connection
:表示是否需要持久连接。 Connection: keep-alive
当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的 网页,会继续使用这一条已经建立的连接 . Connection: close
代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接curl -I
响应头信息:
Accept-Ranges:[bytes]
null:[HTTP/1.1 200 OK]
Cache-Control:[private, no-cache, no-store, proxy-revalidate, no-transform]
Server:[bfe/1.0.8.18]
ETag:["588604c4-94d"]
Connection:[Keep-Alive]
Set-Cookie:[BDORZ=27315; max-age=86400; domain=.baidu; path=/]
Pragma:[no-cache]
Last-Modified:[Mon, 23 Jan 2017 13:27:32 GMT]
Content-Length:[2381]
Date:[Sat, 10 Jun 2017 03:38:14 GMT]
Content-Type:[text/html]
响应头常用信息:
HTTP/1.1 200 OK
Cache-Control:no-cache
作用一模一样 ,Pargma只有一个用法, 例如: Pragma: no-cache
Cache-Control:Public
可以被任何缓存所缓存() Cache-Control:Private
内容只缓存到私有缓存中 Cache-Control:no-cache
所有内容都不会被缓存Content-Length
的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。浏览器缓存一般是前端工程师必须要掌握的,但是,我们作为后端开发也需要了解一下,毕竟技多不压身。
它就是我们在打开一个有缓存的网页时,浏览器会将其自动下载保存到本地(副本)。我们一般通过ctrl+f5来强制刷新本地缓存。
Cache-Control
:缓存控制头信息,是关于浏览器缓存的最重要的设置,不仅可以控制浏览器,还可以覆盖其他设置(如Expires和Last-Modified)或代理服务器。另外,由于浏览器的行为基本相同,这个属性是处理跨浏览器缓存问题的最有效的方法。
Pragma
:与Cache-Control功能类似。Pragma属于通用首部字段,在客户端上使用时,常规要求我们往html上加上这段meta元标签,如:<meta http-equiv="Pragma" content="no-cache">
用于告诉浏览器每次请求页面时都不要读缓存,都得往服务器发一次请求才行。
说明:仅有IE才能识别这段meta标签含义;它不一定会在请求字段加上Pragma,但的确会让当前页面每次都发新请求(仅限页面,页面上的资源则不受影响)。
Expires
:
过期头信息,通常后面跟一个时间,超过这个时间缓存内容将会失效。在客户端上使用时,我照样可以加上meta元标签,如:
<meta http-equiv="expires" content="Sun, 04 Jun 2017 14:40:01 GMT">
说明:同样也只有IE能够识别,如果希望每次刷新页面都能发新请求,那么可以把“content”里的值写为“-1”或“0”。Pragma字段的优先级会高于Pragma。
Last-Modified/ETag
缓存校验字段;用于判断控制文件是否有修改.
本文发布于:2024-01-28 20:17:23,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170644424610010.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |