TCP和UDP、GET和POST、Session和Cookie

计算机网络三大必问不同点

Posted by renchao on July 20, 2017

[TOC]

TCP VS UDP

TCP UDP
传输层控制协议 用户数据报协议
面向字节流 面向报文
面向连接(三次握手四次挥手) 面向非连接
可靠(窗口,拥塞控制,流量控制) 速度慢 不可靠 快速 无阻塞
一对一 一对一 一对多 多对多
按序发送 按序到达 超时重传 尽可能交付 不保证能到达或有序
首部20字节 首部8字节
应用领域:对网络通信质量有要求,如数据要求准确无误的传输,在应用层使用HTTP、HTTPS、FTP等传输文件,POP、SMTP传输邮件 性能要求大于质量,要求速度,实时性,如语音视频通话,直播,大部分应用无需维持连接,需要低功耗等

但是,随着网络技术的发展,网速已不再是传输的瓶颈,UDP简单速度快的优势在越来越多的场景下取代了TCP。

网速的提升给UDP稳定性提供可靠网络保障 网速的提升让网络传输的延迟和稳定性随之改善,如果再使用应用层重传,能够完全确保传输的可靠性。

对比测试结果UDP性能优于TCP 为了提升浏览速度,Google基于TCP提出了SPDY协议以及HTTP/2。Google在Chrome上实验基于UDP的QUIC协议,传输速率减少到100ms以内。(SPDY已经被谷歌废弃并将开发技术转移到HTTP/2上)

SPDY:下一代HTTP协议 试图取代 TCP 的 QUIC 协议到底是什么

TCP设计过于冗余,速度难以进一步提升 TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程以及重传策略。由于TCP内置在系统协议栈中,极难对其进行改进。

UDP协议以其简单、传输快的优势,在越来越多场景下取代了TCP

如何保证UDP的可靠

UDT协议

自己设计的话,可以在发送方将消息加上序列,保存序列,接收方得到数据返回确认消息,发送方设置一个定时器,定时检查发送了但没有返回确认的消息,如果没有返回则重传。

GET VS POST

get和post到底什么区别,别再以讹传讹了

GET POST
向服务器索取数据 向服务器提交数据
浏览器回退后是无害的 会再次提交请求
只能进行URL编码 支持多种编码
请求参数会被完整保留在浏览器的历史纪录里 参数不会被保留
参数的数据类型只能是ASCII字符 没有限制
???不安全,参数直接暴露在URL里 ???较为安全
???参数包含在URL里 ???参数在请求体里
???请求在URL传送的参数是有长度限制的 ???没有长度限制

上面?的意思时说,这些区别都是错的!

其实GET和POST本质上就是TCP连接,并无差别,但是由于HTTP和浏览器服务器的规定,导致在应用过程中有了这些差别。

一一解释:

  1. get和post与数据如何传递没有关系

    get和post是由http协议定义的。在http协议里,方法和数据是正交的两个概念,也就是说,使用get还是post与应用层的数据如何传输是没有相互关系的。

    http没有要求如果是post,参数就一定要在请求体里;也没有要求是get,参数就一定要放在url的后面而不能放在body中。

    那么为什么大家会认为get和post分别要放在url后和body里?这在html标准中有相似的描述,但是这只是html标准对http协议的用法的规定,怎么能当成get和post的区别呢?也就是如果用post时非要在url后加参数,有些服务器会识别参数,有些不会,不保证可靠而已。而且现在的服务器都支持get中包含body这样的请求。

  2. http协议对get和post都没有对长度的限制

    http协议明确指出http头和body都没有长度的要求,而对于url长度的限制,主要是由于:

    • 浏览器。不同的浏览器对于url的长度的限制是不同的。
    • 服务器。url长了对服务器也是一种负担,原本一个会话就没有多少数据,现在如果有人恶意地构造几个几兆大小的url不停访问你的服务器。服务器最大并发数显然会下降。另一种攻击方式是,把告诉服务器Content-Length是一个很大的数,然后只给服务器发一点数据,那服务器就一直在这里等待数据包,哪怕有超时设置,这种故意的次次访问超时也会让服务器吃不了兜着走。所以为了安全和效率,服务器会给url长度加限制。但这个限制是针对所有http请求,与get、post没有关系。
  3. post更安全?

    觉得post比get安全无非是get明文放在地址栏后,但是post也只是在body里把参数encode或者base64了而已,这种加密是可逆的,会一点安全的人,很容易就逆向破解了。

所以一点区别,就是get索取数据,post修改数据而已!

还有一个重大区别:

GET POST
产生一个TCP数据包 产生两个TCP数据包

对于GET来说,浏览器会把request header和data一并发出去,服务器再响应200,返回数据。

而POST来说,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200后,返回数据。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

  • GET与POST都有自己的语义,不能随便混用。
  • 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
  • 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

Session和Cookie

因为HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。所以在例如购物车这种场景下,添加到购物车的逻辑,服务器怎么知道应该添加到我的购物车里。所以需要某种机制来标识具体的用户和状态。

那么服务端如何识别某个用户?Cookie此时就登场了。每次HTTP请求时,客户端都要发送相应的Cookie信息到服务端,这样服务器就知道你是谁了,相当于是一个通行证。

Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用Response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容(因此可以设置Secure保证只能在SSL中传输)。如果浏览器把Cookie功能禁用了,那就会失效。Cookie会有有效期。Cookie不可跨域名,百度的Cookie不可以在谷歌上使用。

Cookie还有一个功能就是将一些登录信息保存起来,下次登陆不用输入,网站页面的脚本可以直接读取这个消息,就自动帮你把用户名填充了,这也是Cookie(甜头)的来历。

Session

除了使用Cookie,浏览器中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

在服务端保存Session的方法有很多,内存,数据库,文件都可以,大型网站一般都会有Session服务器集群,用来保存会话,这时Session都是保存在内存中,使用一些缓存服务比如Memcached之类的来存放Session。

虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSSESIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。

URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。

总结一下:

Session保存在服务端,追踪用户状态;Cookie保存在客户端,记录用户信息,也是实现Session的一种方式。

Session的运行依赖Session ID,而Session ID存在Cookie里,所以禁用Cookie可能会失效,不过可以在URL的参数里传入Session ID。

因此,维持一个会话的核心就是:Session ID。