Network
TCP(传输控制协议)
-
三次握手:
- 客户端初始为
CLOSED
状态,服务器初始化为LISTEN
状态。
- 客户端初始为
-
客户端发送
SYN=1,seq=x
并进入SYN_SEND
状态,SYN=1
是建立连接的讯号,x
是一个随机序列号,seq
主要是来解决网络包乱序的问题。
-
客户端发送
-
服务端发送
SYN=1,ACK=1,seq=y,ACKNum=x+1
并进入SYN_RCVD
状态,ACK=1
表示这是一个响应,y
是服务端产生的随机序列号,ACKNum
是客户端发来的seq + 1
。
-
服务端发送
- 客户端先检查
ACKNum
是不是等于第一次发的seq + 1
来确认这个服务端是没有丢包的。然后客户端发送ACK=1, ACKNum=y+1
,进入ESTABLISHED
状态,服务端收到包以后也进入ESTABLISHED
状态。
- 客户端先检查
-
数据传输:
- 客户端发送
seq=x+1,ACKNum=y+1
- 客户端发送
-
服务端检查ACKNum是否等于上一次发的
seq + 1
,来确认是否丢包,如果正常就发送ACKNum=x+2
。
-
服务端检查ACKNum是否等于上一次发的
-
四次挥手:(下面假设是客户端申请断开)
-
客户端发送
FIN=1,seq=x
并进入FIN_WAIT_1
状态,FIN=1
是关闭连接的讯号,第一次挥手客户端是在表示自己已经没有数据可以发送了,但是仍然可以接受数据。
-
客户端发送
-
服务端发送
ACK=1, ACKNum=x+1
并进入CLOSE_WAIT
状态,这其实是一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接??突Ф私邮盏秸飧鋈啡习?,进入FIN_WAIT_2
状态,等待服务端关闭连接。
-
服务端发送
-
服务端准备好关闭连接后发送
FIN=1,seq=y
并进入LAST_ACK
状态,这是在向客户端发送结束连接请求。
-
服务端准备好关闭连接后发送
-
客户端接收到来自服务端的关闭请求,发送
ACK=1,ACKNum=y+1
,并进入TIME_WAIT
状态。服务端接收到这个确认包之后,关闭连接,进入CLOSED
状态??突Ф说却四掣龉潭ㄊ奔浜?,没有收到服务端的ACK,就认为服务端已经正常关闭连接,于是自己也关闭连接,进入CLOSED
状态。
-
客户端接收到来自服务端的关闭请求,发送
发送方缓冲区:发送方应用进程调用
write
时,内核从该应用进程的缓冲区复制所有的数据到发送缓冲区,如果缓冲区容不下所有的数据,该应用将会被睡眠。在从缓冲区发送到对端的过程中,伴随来自对端的ACK不断到达,本端TCP才能从缓冲区中丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。接收方缓冲区:接收方发送确认报文的同时,会携带上自己缓冲区的剩余大小,这个剩余大小就被称为窗口,指出窗口大小的通知就叫窗口报告。数据会先被接收方放到缓冲区中,然后再由应用取走,如果应用的处理速度低于传输速度的话,就会出现缓冲区爆满的情况。这时就要发送零值窗口通告,并停止数据发送,直到应用将数据消化掉,接收方重新通知一个正值窗口。
-
重传:发送端会有一个重传定时器,如果传输出去的数据包在重传定时内没有获得确认反馈,那么就会向接收端重新传输。但是这边就需要考虑到没有获得确认反馈的原因有可能是当前的网络流量负载已经很大了,那么这样多次的重传会更加加大这个问题,所以做了一下的优化。
- 自适应重传:核心是对重传定时器的时间进行自适应,TCP会记录一系列的往返延迟估值(收到回复的时刻-发送数据的时刻),然后通过加权平均值和方差线性组合为时间。
- 拥塞控制:核心是对重发送数据包的量进行控制, 当报文丢失的时候,先以发送单报文进行试探,收到确认后再加倍发送。以此类推,直到TCP发送的数据到达接收方窗口的一半为止,然后线性增长。
DNS解析
比如 m.xyz.com
主机想知道另一个主机 y.abc.com
的IP地址:
-
主机
m.xyz.com
先向本地服务器dns.xyz.com
进行递归查询。 - 本地服务器先向一个根域名服务器查询。
-
根域名服务器告诉本地服务器,下一次应查询的顶级域名服务器
dns.com
的IP地址。 -
本地域名服务器向顶级域名服务器
dns.com
进行查询。 -
顶级域名服务器
dns.com
告诉本地域名服务器,下一步应查询的权限服务器dns.abc.com
的IP地址。 -
本地域名服务器向权限域名服务器
dns.abc.com
进行查询。 -
权限域名服务器
dns.abc.com
告诉本地域名服务器,所查询的主机的IP地址。 -
本地域名服务器最后把查询结果告诉
m.xyz.com
。
为了加速dns解析过程,通常都会在域名服务器中使用了高速缓存,在本机上使用了hosts文件。而当我们访问一个域名的时候:
- 先读取浏览器缓存
- 如果未命中,接着读取本地hosts文件
- 如果未命中,则向DNS服务器发送请求
前两步就是DNS本地解析
HTTP
HTTP 方法:GET 对比 POST
-
GET
请求可被缓存 -
GET
请求保留在浏览器历史记录中 -
GET
请求可被收藏为书签 -
GET
请求有长度限度 - 其实最主要的还是语义,并且
GET
请求是幂等(多次运行后结果相等)的。
跨域请求
由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
-
jsonp:说说JSON和JSONP,也许你会豁然开朗
- 由于浏览器对凡是拥有
src
这个属性的标签都拥有跨域能力,所以我们就在页面上准备一个函数,远端js文件中直接调用,通过<script>
标签把js文件引入到页面。 - 不支持 POST 请求。
- 由于浏览器对凡是拥有
- Proxy代理:首先将请求发送给后台服务器,通过服务器来发送请求,再将请求的结果传递给前端。
-
CORS:可以通过设置 CORS headers 即
Access-Control-Allow-
系列来允许跨域。
Agent
node.js 的 http
??槭褂昧艘桓?agent
代理。如果你的http
启动了 keep-alive
那么这个代理相当于一个连接池。这个代理维护了一定数量的 socket
链接,当然都是短链接。http发起请求所用的 socket
都是通过代理获取的。这样就省去了每次发起http请求是创建套接字的时间提高了效率。