Node深入浅出 章节总结(第七章 — 网络编程) 持续更新...

本章重中之重,网络编程可以说是构建 web 服务的基石,有很多理论基础将在这章讲解,我个人的体会是如果你错过了这章,你仍可正常的搭建 web 服务,继续写接口与sql,跑通业务逻辑,但是你可能根本就不知道这个过程是如何开始到结束的,也就是说即使得到了你想要的结果,你仍然感觉是雾里看花,不知所措。

其实这章的内容在大学的计算机网络课程上都有讲过,但是我想大部分同学都跟我一样,当时听了也感觉没用,所以只是应付考试,一下就忘了,直到现在实践过再回来看之后,才有一种破开云雾见天明的感觉,可以说是突然感觉整个会话过程都清晰了的既视感,写起来不会再有任何恍惚了。

首先学习完本章后,你应该能理解以下几点:

  1. 理解 OSI 七层模型中 应用层 => 网络层 的传输过程,再往下关于网关继续做 RPC 服务或负载均衡的原理如果大家有兴趣,还请自己去多了解,推荐文章(负载均衡原理—LVS实现部分)讲解的真的比较浅显易懂了,多看几遍还是能大概看懂的;
  2. 理解 TCP 服务与 UDP 服务的区别;
  3. 关于 websocket 创建过程中到底干了什么;

理解 OSI 七层模型

在一切开始前我们要先了解,从一个接口发送请求建立一个会话后的开始到结束究竟都干了什么,这就要从 OSI 七层模型开始,七层协议描述了整个会话的过程;

OSI 模型(层数顺序从上到下)职责个人理解
应用层HTTP、SMTP、IMAP前端发起 HTTP 请求,本次 TCP 连接会话开始
表示层加密/解密等浏览器代理发起 HTTP 后,进行加密或解密相关请求的头部等信息
会话层通信连接/维持会话通过套接字(接口地址)与服务端的 TCP socket 连接,并维持本次长连接会话
传输层TCP/UDPTCP 解析 HTTP 后开始处理响应请求并做处理
网络层IP校验 TCP 服务启动后监听的 IP 与 端口分发路由并做出响应
数据链路层网络特有的链路接口与硬件层次有关,没实践过,不太理解 = =
物理层网络物理硬件硬件相关了

上三层 应用层、表示层、会话层 都在前端到到服务端响应请求之前已经完成,所以我们经常也将上三层统称为 应用层,这样就成为了 五层,这就是 TCP/IP 的五层协议,应用层统一为 TCP 封装的浏览器代理的 HTTP 请求过程。

所以五层本质上是简单的七层,我们完全可将五层扩展为更为安全的 OSI 七层协议模型,由此,大家就应该了解到 TCP 或 UDP 服务在哪一层了,也知道服务端应用是从哪层开始的了,当 TCP 服务响应回封装后的 HTTP 结果,并在客户端收到后,一次由客户端发起的会话就完整的结束了(注意这里我说的是 TCP 服务)。


理解 TCP 服务与 UDP 服务的区别

  • TCP服务(面向连接的协议)

    概念总结: TCP 是面向连接的协议,传输前需要 3 次握手成功后形成会话,然后服务端与客户端分别提供一个套接字,两个套接字共同形成一次较安全、稳定的长连接。

    疑问:net 模块与 http 模块有什么区别呢?(两者建立服务的代码基本是一样的,具体代码请各位自行查看文档即可)

    解答:http 模块是专门用来实现 http 相关的 api 的,而 http 模块是依赖 net 模块的 (net 模块用于构建 tcp 服务,http 服务继承于 TCP 服务),本质上 http 是一种无状态的短连接,http 从应用层到传输层的过程中每次 http 请求都会建立一个新的 tcp 连接,服务器在处理完这次会话后,由代码立刻控制结束本次连接,如果不结束连接,此连接就会一直处理长连接的情况而导致客户端没有响应。而每次都要新建立一个 tcp 连接效率实在太低,所以在 HTTP/1.1 后,浏览器代理的 HTTP 请求都默认开启了 connection: keep-alive 大家在 http 的请求与响应头部都可以看到这个属性,开启后客户端如果立刻访问同一请求,会延续使用上次的连接,tcp 连接会维持一段时间后才关闭,所以 http 与 net 模块的关联很明显了,http 模块中有很多基于 net 模块封装的部分,所以你完全可以用 net 模块去代替 http 模块,但是在应用上发起 http 请求时,你接收就要自己做封装了。

    最后:http 是无状态的短连接是因为,http 经过三次握手形式 tcp 连接会话后,立刻处理完相关业务后就将有状态的 tcp 长连接关闭了,在这个过程中 http 是没有携带任何握手状态的,这些状态都是 tcp 的,而完成后 tcp 又立刻关闭了,所以 http 本质上就是一个连接发起者的作用,tcp 才是处理响应并结束会话的一方,所以我们称 http 其实是无状态的短连接(因为立刻关闭了 tcp 长连接),这也解释了为什么 tcp 是面向连接的协议,因为它本身并不具备发起者的职责。

    结论:当然 http 模块是为应用而生的模块,在正常写应用时,各位还是别乱用 net 模块哦,不然你就要自己封装 http 了额= =,反正我也暂时不会~只是理论上知道是这么干 ┭┮﹏┭┮

  • UDP服务(面向数据报的连接)

    UDP服务本身既可以作为客户端,也可以作为服务端,因为它本身不是面向连接的,所以并没有限制一个套接字对应一个套接字来维持连接,在 UDP 中,一个套接字可以与多个 UDP 服务通信,udp 自身可直接主动发送信息给 udp 服务进行基于数据的通信,就像我们使用 websocket 的体验一样。

    UDP 本身不需要多次建立连接,一个套接字就可以随意发送数据到服务端,而 TCP 若要再次发送数据,则要通过新的套接字建立新的连接,但是基于数据报的连接是不安全、稳定的,因为接收方并不能判断本次是否收到了数据,所以两者可能需要建立一种规则去判断是否收到,所以每次通信是有可能出现丢包问题的,而 TCP 因为是面向连接的,每次通信都是一次连接,所以能保证每次通信的成功,只是不一定正确而已,反观 UDP 无法保证是否成功,也无法知道正确与否,所以 UDP 本身可能更适合音频、视频一类偶尔丢包不影响全局体验的服务。

http 模块的一些东西我就不讲了,在 TCP 服务一节已经说的很清楚,至于具体构建服务的代码,官方文档已经写的非常清楚了,我再复制粘贴也是没有任何意义的,再应用中使用 http 模块是最便捷的,不需要关注何时要断开连接与连接状态问题,毫无疑问,对于开发者来说效率比 net 模块高的多,但是如果涉及到高并发导致的性能问题时,我们不妨考虑用回 net 模块。


关于 websocket 创建过程中到底干了什么

使用 Node 构建 websocket 的好处

  • 众所周知,大家使用 websocket 的时候会发现,它是基于事件的编程模型,我们会去监听 open 事件,再连接成功后做处理,会去监听 message 事件,去接收消息,会去使用 send 节点,发送消息,整个过程都是基于事件的,而 Node 本身就是事件驱动的,所以对于使用 node 的开发者来说,基本没有任何排斥与不适应性
  • websocket 是客户端与服务端之间保持长连接的通信,也就是 TCP 或 UDP 服务都可以做的事情,而 Node 采用异步的事件驱动方式很好的处理了大量客户端的并发连接。

websocket 主要包括两个部分:握手与数据传输

  1. 握手:客户端建立连接时,通过 http 发起请求升级协议为 websocket,在请求头部我们可以观察到申请升级协议的参数
    Upgrade: webscoket
    Connection: Upgrade

    并且会随机生成一个 Sec-WebSocket-Key ,服务端须接受后与 258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接后,创建 sha1 算法的 hash 后释出 base64 后作为 Sec-WebSocket-Accept 返回给客户端,需要注意的是,这时候服务端监听的时候升级事件 upgrade,是在这个事件的回调内返回 socket.write(headers) 的,注意 headers 是字符串,不是对象。
    为什么是拼接这个字符串? 因为是 RFC 协议规定,我也不知道为什么。。。RFC 6455
  2. 数据传输:协议升级成功后,使用 onmessage 方法便可监听数据的往来。

成熟的 websocket 框架推荐 Socket.io,本人很久以前试着用它创建了一个你画我猜游戏的玩具级demo,自己人玩玩还是可以,实现同步聊天、多人房间、同步接受绘画等数据还是很容易的,文档也比较易懂,非常便利。


最后 https 本质上就是 http + ssl 啦,这个大家都知道啦,这个我就偷懒不写了,因为个人认为这个不是重点,因为如果你需要的话,你自然还是得回来看怎么处理的,没人会去记这个的= =。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值