IP、端口与 Host 分别解决什么问题?

2025-08-07 后端

很多初学者搞不清 IP、端口、Host(主机头)三者的区别,因为它们都参与了"定位一个资源"的过程。这篇文章用一个寄快递的类比贯穿到底,把三个概念一次讲透。

一、先看一个类比

想象你要寄一封信给住在某个写字楼里的朋友:

要素 网络中的对应 解决的问题
XX市XX路XX号(写字楼地址) IP 地址 找到哪台机器
1503 号房(房间号) 端口 找到机器上的哪个程序
张三 收(收件人姓名) Host 找到这个程序上的哪个站点

三层定位,缺一不可。

二、IP 地址:找到哪台机器

IP(Internet Protocol)地址是网络层的概念,它唯一标识了网络中的一台设备(服务器、电脑、手机、路由器等)。

解决的问题:把数据包送到正确的计算机。

两种 IP 版本

IPv4: 192.168.1.1         (32 位,约 43 亿个地址)
IPv6: 240e:390:...:1234   (128 位,几乎无限)

IP 的分层:公网 IP vs 私网 IP

        互联网
    ┌──────────┐
    │ 8.8.8.8   │  ← 公网 IP(全球唯一)
    └──────────┘
          │
    ┌────┴────┐
    │  路由器  │  ← 公网 IP:123.45.67.89
    └────┬────┘
         │
    ┌────┴────┐   ┌────┴────┐   ┌────┴────┐
    │  PC     │   │  手机   │   │  服务器  │
    │ 192.168.│   │ 192.168.│   │ 192.168.│
    │ 1.2     │   │ 1.3     │   │ 1.4     │
    └─────────┘   └─────────┘   └─────────┘
    私网 IP(局域网内唯一,互联网不可路由)

公网 IP 是互联网上的"门牌号",私网 IP 是小区内部的"楼栋号"。

一个 IP 就够了?不够

如果一台服务器只有一个 IP,但上面同时运行着 Web 服务、数据库、SSH 远程登录,数据包到了这个 IP 之后,该交给谁?

这就需要下一层:端口。

三、端口:找到机器上的哪个程序

端口(Port)是传输层(TCP/UDP)的概念,范围是 0~65535。

解决的问题:把数据包交给正确的程序/进程。

端口分类

范围 类型 常见用途
0~1023 知名端口(系统保留) 80(HTTP)、443(HTTPS)、22(SSH)、21(FTP)
1024~49151 注册端口 3306(MySQL)、6379(Redis)、8080(代理)
49152~65535 动态/私有端口 客户端临时分配

端口与 IP 组合

IP 和端口合在一起写作 IP:端口:

192.168.1.4:80      → 该机器的 Web 服务
192.168.1.4:3306    → 该机器的 MySQL 数据库
192.168.1.4:22      → 该机器的 SSH 登录

同一个 IP,不同的端口通向不同的程序。

一个端口对应一个程序就够了?还是不够

现在数据包到了 192.168.1.4:80(Web 服务),但这台服务器上托管了多个网站:

  • www.example.com
  • blog.example.com
  • api.example.com

它们都监听 80 端口,请求来了,该返回哪个网站的内容?

这就轮到第三层:Host。

四、Host:找到这个程序上的哪个站点

Host(主机头)是应用层 HTTP/1.1 协议引入的概念,全称是 Host 请求头。

解决的问题:在一台服务器的一个端口上,区分不同的网站。

为什么需要 Host?

在 HTTP/1.0 时代,一个 IP:端口只能托管一个网站。想托管多个网站就得加 IP 或加端口,非常浪费。

# HTTP/1.0 请求(没有 Host)
GET /index.html HTTP/1.0
# 服务器只能根据 IP:端口 确定网站

HTTP/1.1 标准引入了 Host 头:

# HTTP/1.1 请求(带有 Host)
GET /index.html HTTP/1.1
Host: www.example.com
# 服务器根据 Host 头确定是哪个网站

虚拟主机(Virtual Host)

Nginx/Apache 中的服务器块(server block)正是利用 Host 头来区分不同站点:

# 当 Host 是 www.example.com 时
server {
    server_name www.example.com;
    root /var/www/example;
}

# 当 Host 是 blog.example.com 时
server {
    server_name blog.example.com;
    root /var/www/blog;
}

# 当 Host 匹配不到时(默认站点)
server {
    server_name _;
    root /var/www/default;
}

实际抓包演示

当你访问 https://www.3z.ink/articles/网络基础.html 时,浏览器实际发送的请求头是:

GET /articles/网络基础.html HTTP/1.1
Host: www.3z.ink

Nginx 收到后:

  1. TCP 层:数据包到达服务器 IP(如 1.2.3.4)
  2. 传输层:端口 443,交给 HTTPS 服务
  3. 应用层:Nginx 读取 Host 头 → www.3z.ink → 匹配对应的 server block → 返回对应网站内容

五、三层定位的完整流程

你访问 https://www.example.com:443/page
                    │
          DNS 解析域名 → IP: 93.184.216.34
                    │
    ┌───────────────┴───────────────┐
    │                               │
    ▼                               ▼
IP: 93.184.216.34           Port: 443 (HTTPS)
    │                               │
    │  找到正确的服务器              │  找到服务器上的 HTTPS 服务
    │                               │
    └───────────────┬───────────────┘
                    │
                    ▼
            Host: www.example.com
                    │
           在 HTTPS 服务上找到
           对应的虚拟主机配置
                    │
                    ▼
            返回网站内容

六、HTTPS 的特殊情况:SNI

在 HTTPS 中有一个额外的问题:TLS 握手发生在 HTTP 请求之前。也就是说,在客户端发送 Host 头之前,TLS 握手已经完成了,服务器需要提前知道客户端要访问的是哪个站点,才能出示正确的证书。

解决方案是 SNI(Server Name Indication,服务器名称指示)——在 TLS 握手时就带上域名:

Client Hello
  └── server_name: www.example.com

这样服务器就能提前知道要访问哪个站点,从而出示对应的 SSL 证书。几乎所有现代浏览器和服务器都支持 SNI。

七、总结

概念 层级 解决的问题 类比
IP 地址 网络层 把数据送到正确的计算机 写字楼地址
端口 传输层 把数据交给正确的程序 房间号
Host 头 应用层 把数据交给程序上的哪个站点 收件人姓名

三者逐层细化定位:

IP(哪台机器) → 端口(哪个程序) → Host(哪个站点)

下次遇到多站点部署、反向代理配置、Nginx server_name 匹配等问题时,回想这个三层模型,思路就会清晰很多。