OSI七层协议
应用层
应用程序, 产生数据, 利用网络形成应用
- DNS域名系统
- HTTP超文本传输协议
- SMTP邮件协议
- ...
表示层
负责信息语法语义, 如加解密, 转换, 压缩解压缩
会话层
负责不同机器上用户之间建立和管理会话
TCP实际上实现了这部分功能, 使用一张表存储所有TCB(transmission control block), 来确定每个TCP包属于那个session
TCB除了双方的IP,port,应答序号,还记录了双方的窗口大小,队列,重传等变量
传输层
负责两台主机进程间的数据传输服务(端口号), 将数据分割,交给下一层
- TCP 流传输, 数据分包
- UDP 报文
网络层
两台计算机之间数据传输-数据报, 负责选择合适的网间路由(router)和交换节点.
数据链路层
负责物理寻址, 数据传输实际上是在一段一段的链路上进行, 相邻节点之间, 需要间IP数据报组装为帧, 每个帧包含数据和控制信息
物理层
数据单位为bit, 屏蔽传输介质和物理设备的差异
输入URL到显示页面的过程
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- TCP连接结束
TCP UDP
| TCP | UDP | |
|---|---|---|
| 连接 | 有连接 | 无连接 |
| 方向 | 双向 | 单向 |
| 传输 | 字节流 | 报文 |
| 数据边界 | × | √ |
| 可靠性 | √ | × |
| 有序性 | √ | × |
| 系统资源 | 高 | 低 |
| 首部字节 | 20-60 1500-20IP头-20+TCP头 | 8 1500-20IP头-4UDP头 标准MTU=576-20-8 |
三次握手
--SYN m--> <--SYNn/ACKm+1-- --ACKn+1-->
SYN是握手信号, 向对方发送自己的序列化; ACK是确认信号; m,n为随机数
若服务端发送SYN/ACK后没有收到客户端响应, 会重发, 如果仍然没有响应, 不创建连接. linux中重试5次, 时间间隔为1s, 2s, 4s, 8s, 16s,总共31s, 最后再等待32s
为什么不能两次握手
如果发送方的第一次SYN请求受到网络延迟, 发送方可能重发SYN建立连接. 如果第一次的SYN在连接结束后到达接收方, 则错误地使接收方以为是新的连接请求
四次挥手
--FIN--> <--ACK-- <--FIN-- --ACK-->
接收方发送第二步的ACK后, 可能还有数据要发送, 可以继续发送
接收方收到第四步的ACK即可关闭连接
发送方发完ACK后等待一段时间后才连接关闭
TCP如何保证可靠性
- 数据分包(避免IP分片, 1460+20TCP头+20IP头字节)
- 包编号
- 校验和(首部和数据的检验和)
- 流量控制(滑动窗口:滑动窗口大小=接收方缓冲区剩余大小, 除紧急数据)
- 拥塞控制(拥塞窗口;慢开始,拥塞避免,快重传(收到3个重复确认后立即重传),快恢复)
- 停止等待协议(连续ARQ,发送窗口+累积确认, 缺点Go-back-N)
- 超时重传(定时器动态翻倍防止拒绝服务攻击)
- 选择确认(可以确认成功收到的不连续块,避免大量重传. 默认累计确认)
滑动窗口
发送方滑动窗口:
接收方告知发送方自己的窗口大小, 控制发送窗口的大小
TCP 长连接短连接
短连接: 通过正常的握手建立连接, 只传输一次数据, 四次挥手关闭连接
长连接: 不关闭连接, 由服务端提供保活功能. 超过2个小时无响应, 服务端向客户端发送探测报文段(客户端正常响应则服务端将保活计数器复位;客户端无响应则服务器每隔75s发送一个探测, 若均为反应服务端关闭连接)
HTTP协议
HTTP协议无状态, 即对事务处理没有记忆能力
HTTP请求报文
<method> <URL> HTTP/1.1
<host>
<headers>
<content>
GET请求示例
GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
If-Modified-Since:Thu, 4 Feb 2010 20:39:13 GMT
Cookie:userId=C5bYpXrimdmsiQmsBPnE1Vn8ZQmdWSm3WRlEB3vRwTnRtW < HttpOnly
POST请求示例
POST /books/addbook HTTP/1.1
Host: www.olive.com:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
Content-type: application/x-www-form-urlencoded
Content-length: 40
sex=man&name=Professional
x-www-form-urlencoded即与GET相同的内容格式, 用来传输<form>表单的内容. 但POST请求的内容不会被保存到标签或输出到日志, 且没有长度要求
multipart/form-data如果为<form>表单设置enctype = multipart/form-data, 则会以下面方式传输
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
application/json, text/xml也是常用的格式
HTTP响应报文
HTTP/1.1 200 OK
Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112
Set-Cookie: sid=1342077140226724; path=/; expires=Wed,10-Oct-12 07:12:20 GMT; HttpOnly
<html>...
Set-Cookie的HttpOnly属性表示JavaScript的document.cookie无法获取cookie
常见的响应状态还有:
| 301 | Moved Permanently |
| 302 | Moved Temporarily |
| 304 | Not Modified |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 500 | Internal Server Error |
| 503 | Service Unavailable |
HTTP Keep-Alive
HTTP1.0需设置Connection:Keep-Alive, 服务端收到请求后也在响应中添加同样的字段, 则该HTTP连接是长连接(借助TCP的长连接)
HTTP1.1版本默认情况下所有连接都被保持,加入Connection: close才关闭
Keep-Alive: timeout=5, max=100
//表示这个TCP通道可以保持5秒,max=100表示这个长连接最多接收100次请求就断开
HTTP是无连接无状态的, 实际是使用TCP的长连接.
HTTP因此需要一个东西标识长连接结束. 有以下两种方式:
-
Content-Length
表示总传输长度, 需要传完所有内容断开连接
-
Transfer-Encoding:chunk
动态页面服务是不可能预先知道内容大小, 即如果要一边产生数据,一边发给客户端,服务器就需要使用
Transfer-Encoding: chunked. chunk编码将数据分成一块一块的发生。Chunked编码将使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束
会话追踪
指对同一个用户对服务器的连续的请求和接受响应的监视. HTTP无状态, 用会话追踪保存用户状态.
-
URL重写
URL(统一资源定位符)是Web上特定页面的地址,URL重写的技术就是在URL结尾添加一个附加数据以标识该会话,把会话ID通过URL的信息传递过去,以便在服务器端进行识别不同的用户。
-
隐藏表单域
将会话ID添加到HTML表单元素中提交到服务器,此表单元素并不在客户端显示
-
Cookie
Cookie 是Web服务器发送给客户端的一小段信息,客户端请求时可以读取该信息发送到服务器端,进而进行用户的识别。对于客户端的每次请求,服务器都会将 Cookie 发送到客户端,在客户端可以进行保存,以便下次使用。
客户端可以采用两种方式来保存这个 Cookie 对象,一种方式是保存在客户端内存中,称为临时 Cookie,浏览器关闭后这个 Cookie 对象将消失。另外一种方式是保存在客户机的磁盘上,称为永久 Cookie。以后客户端只要访问该网站,就会将这个 Cookie 再次发送到服务器上,前提是这个 Cookie 在有效期内
Cookie 是可以被客户端禁用的。
-
Session:
在服务器端会创建一个 session 对象,产生一个 sessionID 来标识这个 session 对象,然后将这个 sessionID 放入到 Cookie 中发送到客户端,或如果cookie被禁用, 可用前两种方式
客户端禁用cookie如何实现session
-
设置php.ini配置文件中的“session.use_trans_sid = 1”,或者编译时打开打开了“--enable-trans-sid”选项,让PHP自动跨页传递Session ID。
-
手动通过URL传值、隐藏表单传递Session ID。
-
用文件、数据库等形式保存Session ID,在跨页过程中手动调用。
CSRF(Cross-site request forgery 跨站请求伪造)
在页面上放一个链接, 引诱用户点击, 则用户会不知晓地发送GET请求
解决方案:
- 改用POST请求
- Token验证(随机)
- 验证码
- 检测Referer(用户点击网页上的链接;发送表单;网页加载静态资源时请求headers中有Referer字段)
XSS(Cross Site Scripting 跨站脚本攻击)
在输入中加入javascript代码, 执行
-
HTML excape
对特殊字符替换, 使之显示为正常内容
-
HTML解析库
需要用户输入html标签时, 将用户的输入进行解析,获取其中的数据。然后根据用户原有的标签属性,重新构建HTML元素树。构建的过程中,所有的标签、属性都只从白名单中拿取
SQL注入
-
PreparedStatement(简单又有效的方法)
-
使用正则表达式过滤传入的参数
-
字符串过滤
-
JSP中调用该函数检查是否包函非法字符
-
JSP页面判断代码
HTTP1.0 vs 1.1
- 默认长连接
- 增加24个错误状态响应码
- 缓存处理, headers中加入了更多缓存控制策略
- 带宽优化, 加入range域, 返回码206表示partial
HTTP2.0
- 将原本的消息封装为frame
- 多路复用, 一个request对应一个stream并分配一个id,这样一个连接上可以有多个stream
- header压缩
- 流量控制, flow control(类似receive window)
- 服务端推送(server push)