🎈 九年了,感谢大家 🎏 订阅全年送一年,续订或重订送两年。 立即订阅

Node.js 服务端应用开发 #5:网络基础

前面我们用 Node.js 做了一个 Web 服务器,启动以后大家就可以通过网络使用这个 Web 服务了。这就扯出来一些跟网络相关的概念,地址里的 HTTP 是什么意思,Localhost 是啥玩意,端口号是又干什么用的。这一章我们就来了解一点网络的基础,这会有助于我们以后开发服务端的应用。

传输协议(HTTP)

协议(Protocol)是网络上的设备之间签订的合同,大家都要遵守、履行这个合同才可以正常沟通、交流、合作。也可以把协议想成是一套协调商议出来的方法,比如先干什么,再干什么,怎么干等等,大家可以用这套方法来相互协作,交换数据。

HTTP(HyperText Transfer Protocol) 就是一种传输数据用的协议。客户端与服务端,服务端与服务端之间都可以通过这种协议传输数据。我们之前搭建了一个 Web 服务,这个服务遵照了 HTTP 协议的要求,所以客户端可以使用 HTTP 这种协议使用我们的 Web 服务。

还有一种叫 HTTPS 的协议,S 指的是 Secure(安全),所以 HTTPS 就是一种更安全的 HTTP 协议。设备之间通过网络,使用 HTTP 协议相互传输数据,数据在运输途中可能会被一些坏蛋获取到(嗅探),这样这些坏蛋就知道用户给服务发了什么数据,或者服务给用户响应了什么数据。如果换用 HTTPS 来运输数据就安全多了,因为这些运输的数据是加密过的,也就是只有用户与服务才知道具体的数据是什么,这样这些小坏蛋们即使打听到了用 HTTPS 运输的数据,它们也看不懂里面到底是什么。

HTTPS 与 HTTP 的主要区别就是一个加密数据一个不加密数据,现在大部分 Web 服务都会选择使用 HTTPS 这种协议,在后面介绍部署应用的时候,再去学习怎么配置 Web 服务使用 HTTPS 协议。

之前我们搭建了一个 Web 服务器,服务器是遵照 HTTP 协议搭建的,所以客户端与服务端就可以使用 HTTP 协议互传数据了。我们在浏览器的地址栏里输入 http://localhost:3000,这种地址形式就说明了是在使用 HTTP 这种协议传输数据。先是 http://,后面是主机名或者 IP 地址,最后还可以设置一下端口号。

网络地址(IP)

互联网就是一个让不同的东西相互连接到一块儿的网络,在这个网络里的东西都需要一个地址,通过这个地址大家才能知道如何互相沟通交流。你发给我点东西,我也给你回过去点东西,如果大家不知道彼此的地址,就没有办法沟通了。这里说的地址就是 IP(Internet Protocol) 地址。

IP 地址看起来像这样:113.128.149.95,这是我家路由器的 IP 地址。42.120.40.68,这是我的一台服务器的 IP 地址。192.168.31.127,这是我现在用的这台电脑的内网 IP 地址。

目前,大部分的 IP 地址都是它的第四个版本的样子,也就是我们常说的 IPv4。这种地址是四个数字,中间用点分隔开。因为互联网上的设备都需要这么一个地址,而且它们还得是唯一的,但是这种数字结合形式的地址的数量是有限的,现在已经快用光了。所以在未来,会使用新版本的 IP 地址,下一个版本应该是 IPv6,所以它们的样子就不会是这种数字的组合了。

IP 地址可以分为公网 IP (Public IP) 与内网 IP(Private IP),公网指的就是互联网。如果一个设备有公网地址,你就可以在任意一台同样接入互联网的设备跟它交流。内网地址指的是内部网络的地址,比如你家一定安装了一台路由器,家里要上网的设备一般都会通过 Wi-Fi 连接到这台路由器,这个路由器会给每台设备都分配一个内网的 IP 地址,这里的这些设备通过路由器组建的网络就是内网,或者也可以称为局域网。

同属于一个内网的设备,它们之间可以通过彼此的内网 IP 地址相互交流,但是如果要跟互联网上的设备连接,就必须要通过一个公网地址。网络服务商(电信、移动)会给你家的这台路由器分配一个公网地址,你家里的设备(电脑、手机、平板 ... )最终都会通过这个公网 IP 访问互联网。

路由器跟你要上网的这台设备在同一个内网里面,也就是路由器与终端设备各自都有一个内网的 IP 地址,所以它们之间才能够通信交流。路由器上除了拥有一个内网的 IP 地址,负责跟内网设备通信。它还有一个公网的 IP 地址,负责跟外面联系。

比如你在家里的一台电脑上要打开一个网站,这个网络请求会先交给你家的路由器,然后由这个路由器去请求你需要打开的网站服务器,服务器响应回来的数据,也会通过家里的这台路由器转交给你的电脑。因为你的电脑只有一个内网 IP 地址,没有办法直接跟互联网连接,你的路由器有公网 IP,所以家里的所有想上网的设备都只能通过你的路由器才行。

互联网特别留了几个 IP 地址段给内网使用,下面这些都是内网 IP 地址:

  • 10.0.0.0 – 10.255.255.255
  • 172.16.0.0 – 172.31.255.255
  • 192.168.0.0 – 192.168.255.255

任务<MacOS>:知道电脑的 IP 地址

  1. 打开 系统偏好设置
  2. 打开 网络, 观察 Wi-Fi 的状态,上面会显示内网 IP 地址
  3. 在终端,执行 ifconfig ,同样可以查看 IP 地址

任务<Windows>:知道电脑的 IP 地址

  1. 打开系统的 设置
  2. 打开 网络和 Internet,选择 以太网,再点击 网络,在页面底部会显示电脑的 IP 地址
  3. 在终端,执行 ifconfig ,同样可以查看 IP 地址
Windows IP 配置


以太网适配器 Ethernet0:

   连接特定的 DNS 后缀 . . . . . . . : localdomain
   本地链接 IPv6 地址. . . . . . . . : fe80::58e9:6420:c40e:91c1%12
   IPv4 地址 . . . . . . . . . . . : 192.168.233.129
   子网掩码  . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . : 192.168.233.2

任务:知道终端设备上网用的公网 IP 地址

如果你的电脑是通过 Wi-Fi 连接路由器上网的,那你在电脑上看到的 IP 地址一般就是路由器分配给这台电脑的一个内网的 IP 地址。在搜索引擎比如百度 / Google,搜索关键词 IP,会出现你的公网 IP 地址。在终端,用 curl 命令请求 ip.me 或 curlip.me 这种网站,也可以查到自己的公网 IP 地址。

→ curl curlip.me
IPv4: 113.128.151.181
Geo2IP: 中国山东济南电信

内网 / 局域网

用一台网络设备,比如一台简单的路由器,我们就可以组织一个网络,这个网络叫内网,局域网,或者也可以叫做私有网络。一般在我们家里都有这样一个网络,家里的电脑,平板,手机都会连接到这个网络上,路由器会给这些设备各自分配一个内网的 IP 地址。这些同在一个网络里的设备可以相互连接。

我的一台电脑通过 Wi-Fi 连接到了一台路由器,路由器给我的电脑分配的内网 IP 地址是 192.168.31.127,通过这个地址,我可以知道这个路由器组建的网络,用的是 192.168.31.x 这个网段的 IP 地址,这里的 x 可以是 1 到 255 之间这些数字。也就是如果有其它设备连接到这台路由器同样可以得到一个这样的 IP 地址,比如我的一部手机分配到的 IP 地址是 192.168.31.159

我的电脑与手机在同一个局域网里,它们之间是可以相互连接的,你可以使用 ping 命令来测试是否能与指定的设备连接。比如在我的电脑上,打开终端,然后执行一下 ping 命令:

→ ping 192.168.31.159
PING 192.168.31.159 (192.168.31.159): 56 data bytes
64 bytes from 192.168.31.159: icmp_seq=0 ttl=64 time=103.318 ms

在 ping 命令的后面,可以设置要测试连接的设置的 IP 地址或者主机名,如果你能看到类似上面这样的结果,说明这台设备可以跟地址是 192.168.31.159 这台设备连接。ping 命令会往指定的地址发送数据包,对方收到数据包会作出一个回应。不过要注意并不是所有的设备都会对 ping 命令作出回应,可以通过配置让设备禁止作出这种回应,因为做出这种回应会浪费资源。

证明了电脑与手机之间可以相互连接,我们就可以在手机的浏览器上,测试访问在电脑上运行的服务端应用了。假设在电脑上运行了之前我们一块儿做的 Web 应用,在手机浏览器可以用电脑在内网的 IP 地址访问到这个应用,我这里就是 http://192.168.31.127:3000 。

主机名,域名,DNS

IP 地址太难记住了,也没啥个性,我们还是给网络设备起个名字吧,以后可以用这个名字来使用在这些网络设备提供的服务,于是就有了主机名,英文是 Hostname。

比如你做了一个网站,开发了一个服务端应用,放在了一台服务器上运行。我们可以再去申请一个域名,然后可以再基于这个域名配置一个主机名,让它指向运行应用的那台服务器的网络地址,这样别人就可以用这个主机名来使用你的网站或者应用了。域(Domain),是领域,地盘的意思,域名(Domain name),指的就是一个领域或一个地盘的名字。

找一个域名服务商,申请注册一个域名以后,就可以配置一些解析记录。比如我的一个域名是 ninghao.net,我让这个域名指向我的主网站的服务器,地址是 47.97.10.87。然后我又配置了一个主机名 talk.ninghao.net,让它指向我的另一台服务器,地址是 101.37.27.240,这台服务器提供了一个社区服务。

我配置的这两条域名解析记录都对应了一个具体的 IP 地址,用户通过查询 DNS(Domain Name System) 服务就可以知道我配置的域名与主机名对应的具体的 IP 地址是什么。接入到互联网的设备都会事先配置好 DNS 服务器,在访问网站的时候,电脑会先去查询这些 DNS 服务器,获取到域名主机名对应的 IP 地址是什么,然后再向这些 IP 地址发出请求。

任务:知道主机名指向的 IP 地址

  1. 打开终端
  2. 执行 ping ninghao.net,观察得到的结果
  3. 按下 ctrl + C,停止运行
  4. 执行 ping talk.ninghao.net 观察得到的结果
  5. 按下 ctrl + C,停止运行

在命令行下面,执行 ping 命令,后面加上一个具体的主机名。

→ ping ninghao.net
PING ninghao.net (47.97.10.87): 56 data bytes
64 bytes from 47.97.10.87: icmp_seq=0 ttl=87 time=26.299 ms

命令会先去 DNS 那里查询一下,ninghao.net 指向的 IP 地址是什么,观察执行的结果,上面会显示一个 IP 地址。

localhost,127.0.0.1,hosts 文件

localhost 是个特别的主机名,它指的是本地主机,也就是当前这台电脑。之前我们在自己的电脑上做了一个 Web 服务器,启动以后,就可以在浏览器通过 localhost 这个主机名访问到这个 Web 服务了。

localhost 这个主机名对应的 IP 地址是 127.0.0.1,这个地址指向的就是本地这台电脑,也就是在一台电脑上请求 127.0.0.1 这个地址,这个请求就会发送给它自己。所以我们可以通过 localhost 这个主机名,访问在本地电脑上运行的服务。

localhost 主机名,对应 127.0.0.1 这个地址,是在一个叫 hosts 的文件里配置的。Windows,macOS,还有 Linux 系统里面,都有这么一个文件。在这个文件里你可以手工配置一下,让某个主机名指向某个 IP 地址,这样在这台设备上访问这个主机名的时候,电脑就不会到 DNS 那里查询了,会直接访问我们自己为这个主机名配置的那个 IP 地址。

任务:理解主机名配置文件<hosts>

  1. 在终端,执行 ping localhost,观察结果
  2. 查看系统里的 hosts 文件,观察结果

在终端,执行:

ping localhost

你会发现这个 localhost 主机名指向的地址是 127.0.0.1,在 Windows 系统里可能是 ::1,这是一个 IPv6 地址,指的也是本地主机的地址。127.0.0.1 是一个 IPv4 地址。

操作系统里有个 hosts 文件可以手工配置主机记录,让某个主机名指向某个 IP 地址。在 macOS 系统里,这个文件是在 /etc/hosts,在 Windows 系统里,这个文件是在系统盘下的 _\Windows\System32\Drivers\etc\hosts _。查看这个 hosts 文件里的内容,你会发现这样的记录:

127.0.0.1    localhost
::1          localhost

127.0.0.1(IPv4) 与 ::1(IPv6) 这两个 IP 地址,指向的都是 localhost 这个主机名,所以我们在访问 localhost 这个主机名的时候,就可以打开在本地电脑上运行的服务了。

在 Windows 操作系统里,你会发现上面这两条记录是被注释掉的,因为它们前面有 # 号。所以 Windows 系统应该用了其它的方法,让 localhost 这个主机名指向表示本机的 IP 地址。

访问一个主机名的时候,电脑会先检查这个 hosts 文件里的记录,如果没找到就会去问 DNS 。也就是如果你在 hosts 文件里自己配置了主机记录,电脑在访问这些主机的时候就不会问 DNS 了,会直接访问你为主机名设置的对应的那个 IP 地址。你在这个文件里做的配置只会影响到你当前这台电脑,不会影响其它的设备。

你可以做个实验,编辑一下 hosts 文件,在里面添加这样一条记录:

127.0.0.1    baidu.com

保存一下 hosts 文件,然后在命令行里 ping 一下 baidu.com,你会发现你的电脑会认为这个主机名指向的 IP 地址是 127.0.0.1 ,也就是现在如果你在浏览器上访问 baidu.com,这个请求会发送到你自己这台电脑上。

任务:自定义本地主机名

localhost 这个主机名表示的是本地主机,如果你不喜欢这个名字,或者你需要其它的表示本地主机的名字,可以编辑一下系统里的 hosts 文件。

  1. 在终端,执行 ping xb2-node,观察结果
  2. 编辑 hosts 文件,添加自定义主机名记录
  3. 在终端,执行 ping xb2-node,观察结果

在终端,先 ping 一个 xb2-node 这个主机名:

→ ping xb2-node
ping: cannot resolve xb2-node: Unknown host

提示不认识 xb2-node 这个主机,下面可以使用编辑器打开系统的 hosts 文件,可以使用 vi 命令,或者 VSCode 编辑器打开这个文件。

macOS:

code /etc/hosts;

Windows:

code /c/Windows/System32/Drivers/etc/hosts;

在这个 hosts 文件里添加一条新的记录:

127.0.0.1   xb2-node

保存一下 hosts 文件,可能会提示没有权限,选择用管理员身份重试,输入用户密码,再确定一下。然后回到终端,重新 ping 一下 xb2-node 这个主机名,这次你会发现这个主机名指向的就是 127.0.0.1 这个 IP 地址。现在访问我们在本地电脑上运行的应用,可以用 localhost 这下主机名,也可以用 xb2-node 这个主机名。

交流通道(Port)

端口(Port) 就是跟服务交流用的一个通道。在一台设备上,可能会同时运行多个服务,服务在运行的时候可以选择使用一个端口号,这个端口号,就是跟这个特定服务交流用的一个专用通道。端口号可以是 1 到 65535 之间的数字。

之前我们一块儿用 Node.js 搭建了一个 Web 服务,设置让它使用的端口号是 3000。如果你想同时再去运行一个 Web 服务,就只能选择一个其它的端口号,比如 30018081 ... 因为 3000 这个端口号已经被一个服务占用了。

不同类型的服务,默认会使用一个特定的端口号,比如 Web 服务默认的端口号是 80,加密的 Web 服务默认用的端口号是 443,MySQL 类型的数据库服务,默认的端口号是 3306。这些默认的端口号是可以修改的,也就是你可以自己选择让它们通过哪个端口号来提供服务。

之前我们创建的 Web 服务,设置让它用的端口号是 3000,所以访问它的时候,用的地址是 http://localhost:3000http 是用的一种网络协议,localhost 是主机名,冒号右边的 3000 是服务选择使用的端口号。通过主机名,能找到提供服务的设备的 IP 地址,通过端口号,可以跟在这台设备上运行的一个特定的服务交流。如果在创建 Web 服务,给它选择的是 80 端口,访问这个服务用的地址就可以是 http://localhost ,浏览器会自动帮我们加上默认的端口号。

任务:理解端口的作用

1:运行应用

在终端,进入到我们之前开发的项目所在的目录,然后运行一下应用:

node src/main.js

2:请求应用

新建一个终端标签,可以用 curl 命令请求一下应用,执行:

curl http://localhost:3000

curl 命令会对指定的地址发出请求,地址里包含了服务用的端口号 3000,请求这个地址可以得到服务端应用响应回来一个 JSON 数据。

3:修改应用监听的端口

下面回到项目,然后修改一下服务用的端口号,换成 80 端口:

server.listen(80, () => {
  console.log('🚀 服务已启动!');
});

重新启动一下服务。

4:请求应用

再用 curl 请求一下,请求的时候地址里设置的端口号应该换成 80,因为这是 HTTP 默认用的端口号,所以也可以不用特别指定端口号。

curl http://localhost:80
curl http://localhost

如果我们现在请求地址 http://localhost:3000,就会出现下面这样的提示:

curl: (7) Failed to connect to localhost port 3000: Connection refused

意思就是连接 localhost 主机,3000 端口的时候,这个连接被主机拒绝了,因为请求的地址里用的是 3000 这个端口,在我的电脑上并没有服务使用这个端口,所以连接就会被拒绝。最后再修改一下项目,把应用使用的端口号换成原来的 3000 。

参考课程

https://ninghao.net/course/8168



微信好友

用微信扫描二维码,
加我好友。



微信公众号

用微信扫描二维码,
订阅宁皓网公众号。



240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

12921
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点