Skip to content

連接埠與 localhost

💡 學習指南:當你執行 npm run dev,終端機裡出現 http://localhost:5173 時,你有沒有想過:localhost 是什麼?5173 又代表什麼?為什麼有時候會報 EADDRINUSE 錯誤?本章就來把這些日常開發中天天見、卻很少深究的概念一次講透。

在開始之前,建議你先補兩塊「基礎磚」:


0. 引言:那個天天見的 localhost:5173 到底是什麼?

1
2
3
4
5
1. You run npm run dev
Terminal
$ npm run dev

> vite

  准备就绪...
Listening
Browser
等待你打开Browser...
💡 You type the start command in terminal
What is an HTTP Server?
🏪
Imagine a service windowHTTP 服务器就像一个"永远开着的服务窗口"——它一直等在那里,有人来问就回答,没人来就静静等着。
📋
Only understands one "code"这个窗口只听得懂 HTTP 协议的请求格式(比如 GET /index.html),然后把对应的文件内容返回给你。
⚙️
Dev Server = Enhanced WindowVite、Webpack 的开发服务器不只是"原样返回文件",它还会即时编译你的代码(Vue → JS、TS → JS、Sass → CSS),然后再返回给Browser。
One-line Summary:Dev server = An HTTP server running on localhost + Real-time code compiler. It listens on a port, and when browser requests, it returns the compiled code.

每個開發者的日常都離不開這一行輸出:

➜  Local:   http://localhost:5173/

但你有沒有想過,這短短一行字裡,藏著好幾個關鍵概念:

  • http:// → 通訊協定(用什麼語言對話)
  • localhost → 目標位址(找誰)
  • :5173 → 連接埠號(找到之後,敲哪扇門)

搞懂這三件事,你就能理解 90% 的開發環境網路問題。接下來我們逐個拆解。


1. 什麼是連接埠?(IP 是大樓,連接埠是房間號)

1.1 一個直覺比喻

想像一台伺服器是一棟大樓:

  • IP 位址(如 192.168.1.100)就是大樓的門牌位址——告訴你「去哪棟樓」。
  • 連接埠號(如 :80)就是樓裡的房間號——告訴你「進哪間房」。

一棟樓裡可以同時有餐廳(80 號房)、咖啡廳(443 號房)、辦公室(22 號房)。同理,一台電腦上可以同時執行 Web 伺服器、資料庫、SSH 服務,各自佔用不同的連接埠。

👇 動手試試看: 點擊下面的「房間門牌」,模擬向不同連接埠發起連線。注意觀察:當連接埠「開著」(有程式在監聽)和「關著」時,分別會發生什麼?

Select a "building":
Web Server BuildingIP: 192.168.1.100
80
HTTPWeb access entry
🟢 Listening
443
HTTPSEncrypted web entry
🟢 Listening
22
SSHRemote management channel
🟢 Listening
3306
MySQLDatabase (closed)
🔴 Closed
Core Analogy:IP 地址 = 大楼地址,端口号 = 房间门牌号。一台电脑上可以同时运行多个服务,每个服务"占用"一个端口号,就像同一栋大楼里的不同房间。

1.2 連接埠號的取值範圍

連接埠號是一個 0–65535 之間的整數(共 65536 個)。這麼多連接埠被分為三個區間:

區間範圍用途舉例
系統連接埠0 – 1023預留給標準協定,一般使用者不能隨意佔用80 (HTTP)、443 (HTTPS)、22 (SSH)
註冊連接埠1024 – 49151給常見應用註冊使用3306 (MySQL)、5432 (PostgreSQL)、6379 (Redis)
動態連接埠49152 – 65535作業系統臨時分配瀏覽器發請求時,系統隨機分配一個來源連接埠

為什麼你的開發伺服器喜歡用 3000、5173、8080?因為這些都在「註冊連接埠」範圍內,不需要管理員權限就能監聽,又不太容易和系統服務衝突。

1.3 開發中常見的連接埠號速查

👇 動手試試看: 輸入連接埠號或服務名搜尋,點擊任意一行可以展開查看使用範例。

PortServiceDescriptionExposure Risk
80HTTP网页访问(未加密)安全
443HTTPS网页访问(加密)安全
22SSH安全远程登录注意
21FTP文件传输敏感
3306MySQLMySQL 数据库敏感
5432PostgreSQLPostgreSQL 数据库敏感
27017MongoDBMongoDB 数据库敏感
6379RedisRedis 缓存敏感
3000Node/ReactNode.js / React 开发服务器安全
5173ViteVite 开发服务器安全
8080通用 HTTPHTTP 备用端口 / 代理安全
8000Django/PythonDjango / Python HTTP 服务安全
5000FlaskFlask 开发服务器安全
4200AngularAngular 开发服务器安全
53DNS域名解析注意
25SMTP邮件发送注意
0 – 1023
System PortsReserved for standard services (HTTP, SSH, etc.), regular users cannot occupy.
1024 – 49151
Registered PortsFor common applications (MySQL 3306, Redis 6379, etc.), most encountered in development.
49152 – 65535
Dynamic PortsTemporarily assigned by OS, like when your browser makes requests, system randomly assigns one.
Security Alert:数据库端口(3306、5432、27017、6379)绝对不要直接暴露到公网!生产环境应只允许内网访问或通过 SSH 隧道连接。

2. 什麼是 localhost?(自己找自己)

2.1 「環回」的核心概念

localhost 是一個特殊的網域名稱,它永遠指向你自己的這台電腦

當你在瀏覽器輸入 http://localhost:3000 時,發生了這些事:

  1. 瀏覽器問作業系統:「localhost 的 IP 是多少?」
  2. 作業系統直接回答:「127.0.0.1」(不需要聯網查 DNS)
  3. 資料封包發往 127.0.0.1,但不會真的離開本機
  4. 作業系統透過「環回介面(loopback interface)」把資料封包折返回來
  5. 監聽在 3000 連接埠上的程式收到請求,返回回應

整個過程不經過網路線、不經過路由器、不需要聯網。

👇 動手試試看: 點擊「發送請求」,觀察資料封包的完整旅程。然後點擊下方的「馬甲卡片」,了解 localhost 的幾種寫法和區別。

🔗
🌐
BrowserYou enter URL in address bar
📖
DNS Resolutionlocalhost → 127.0.0.1 (no internet)
🔄
Network LayerPacket sent to 127.0.0.1 (loopback interface)
⚙️
Local ServiceProgram on port 3000 receives request
📨
Return Response{ "message": "Hello!" }
Your App(Browser)
Request stays on local machine
Local Service(:3000)
Localhost "Aliases" (click to see description)
localhost→ 127.0.0.1
127.0.0.1→ 127.0.0.1
::1→ ::1
0.0.0.0→ 0.0.0.0
This is mapped in your computer's <code>/etc/hosts</code> file. When browser sees <code>localhost</code>, it directly resolves to <code>127.0.0.1</code> without asking DNS server.: 这是写在你电脑 /etc/hosts 文件里的映射。浏览器看到 localhost 时,直接解析为 127.0.0.1,不会去问 DNS 服务器。
Core Concept:localhost 就是"自己找自己"。数据包通过环回接口(loopback interface)在本机内部折返,不经过网线、不经过路由器,速度极快且完全安全。

2.2 localhost vs 127.0.0.1 vs 0.0.0.0

這三個概念經常被混淆,但它們的含意完全不同:

寫法含意誰能存取
localhost / 127.0.0.1環回位址,僅本機只有你自己的電腦
0.0.0.0監聽所有網路介面本機 + 區域網路內其他裝置
192.168.x.x區域網路 IP區域網路內的裝置

實際場景

bash
# 只有自己能存取(安全,適合開發)
npm run dev -- --host localhost

# 手機也能存取(適合行動端除錯)
npm run dev -- --host 0.0.0.0

很多框架(如 Vite、Next.js)預設監聽 localhost,所以你的手機即使連著同一個 WiFi 也存取不了。想用手機除錯?加上 --host 參數就行。


3. 連接埠衝突:最常見的開發環境問題

3.1 為什麼會衝突?

一個連接埠同一時刻只能被一個程式監聽。 這就像一個房間只能住一戶人家。

如果你嘗試在同一個連接埠上啟動第二個服務,就會看到這個經典錯誤:

Error: listen EADDRINUSE :::3000

翻譯成人話就是:「3000 號房已經有人住了,你進不去!」

常見的衝突場景:

  • 上次的開發伺服器沒關乾淨,還在背景執行
  • 兩個不同的專案用了相同的預設連接埠
  • 某個系統服務已經佔用了你想要的連接埠

👇 動手試試看: 試著在下面的模擬器裡多次啟動服務。當連接埠衝突時,對比「直接啟動」和「智慧啟動」的不同處理方式。

Try starting:React(default port 5173)
Currently Running Services1 services
Vite:5173🟢 Running
Port Conflict:一个端口同一时刻只能被一个程序监听。如果你看到 EADDRINUSE 错误,说明这个端口已经被占了。要么杀掉旧进程,要么换个端口。

3.2 排查與解決

遇到連接埠衝突時,排查流程非常固定:

macOS / Linux:

bash
# 第一步:查看誰在佔用 3000 連接埠
lsof -i :3000

# 第二步:拿到 PID 後,強制終止
kill -9 <PID>

Windows:

bash
# 第一步:查看誰在佔用 3000 連接埠
netstat -ano | findstr :3000

# 第二步:終止行程
taskkill /PID <PID> /F

很多現代框架(Vite、Create React App 等)遇到連接埠衝突時會自動詢問「是否換一個連接埠?」。但了解底層原理,能幫你更快地排查那些框架幫不了你的疑難雜症。


4. 開發中的「同源策略」與跨域

4.1 什麼是「源」?

瀏覽器有一個安全機制叫做同源策略(Same-Origin Policy):只有協定、域名、連接埠三者完全一致,才算「同源」。

位址 A位址 B是否同源原因
http://localhost:5173http://localhost:5173/about✅ 同源協定、域名、連接埠都一樣
http://localhost:5173http://localhost:3000❌ 不同源連接埠不同(5173 vs 3000)
http://localhost:5173https://localhost:5173❌ 不同源協定不同(http vs https)

4.2 為什麼前後端分離必然遇到跨域?

當你的專案架構是:

前端 (Vite)  →  http://localhost:5173
後端 (Express) →  http://localhost:3000

前端頁面從 :5173 載入,然後用 fetch('/api/users') 去請求 :3000 的介面——連接埠不一樣,觸發跨域限制!

兩種常見解決方案:

方案一:後端設定 CORS

javascript
// Express 後端
app.use(cors({ origin: 'http://localhost:5173' }))

方案二:前端設定代理(推薦)

javascript
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
}

代理的原理:讓 Vite 開發伺服器幫你「轉發」請求。瀏覽器以為自己在和 :5173 通訊(同源),實際上 Vite 在背後偷偷幫你把請求轉給了 :3000


5. 實戰排查:三個最常見的問題

👇 動手試試看: 選擇一個你遇到的問題,跟著步驟一起排查。每一步都可以點擊「執行」查看輸出。

Select a common issue:
🔴
Port OccupiedError: listen EADDRINUSE :::3000
Troubleshooting Steps (1/3)
$lsof -i :3000
Check who is using this port
Troubleshooting Mantra:先确认服务有没有启动(lsof / netstat),再确认端口对不对,最后确认是不是跨域问题。90% 的 localhost 问题都逃不出这三步。

6. 名詞對照表

英文術語中文對照解釋
Port連接埠一個 0–65535 的數字,用來區分同一台機器上的不同網路服務。每個服務「監聽」一個連接埠,等待客戶端連線。
localhost本機主機一個特殊網域名稱,永遠指向本機(127.0.0.1)。用於在不聯網的情況下存取本機上執行的服務。
Loopback Interface環回介面作業系統的虛擬網路介面。發往 127.0.0.1 的資料封包不會離開本機,而是透過該介面「折返」回來。
EADDRINUSE位址已被使用Node.js / 作業系統報的錯誤,表示你要監聽的連接埠已經被另一個程式佔用了。
CORS跨域資源共享瀏覽器安全機制。當前端頁面嘗試請求不同源(協定/域名/連接埠不同)的介面時,需要後端明確許可。
Same-Origin Policy同源策略瀏覽器的安全基石:只允許同協定、同域名、同連接埠的請求自由通訊,阻止跨域的資料讀取。
Proxy代理在開發環境中,代理伺服器代替瀏覽器向後端轉發請求,繞過瀏覽器的同源限制。
0.0.0.0所有介面當服務監聽 0.0.0.0 時,表示它接受來自任何網路介面(本機、區域網路等)的連線。
Well-known Ports知名連接埠0–1023 連接埠的統稱,預留給 HTTP (80)、HTTPS (443)、SSH (22) 等標準協定。
PID行程 ID作業系統為每個執行中的程式分配的唯一編號,用於管理和終止行程。
lsof列出開啟的檔案macOS/Linux 命令,用於查看哪個行程佔用了某個連接埠(lsof -i :連接埠號)。
HMR熱模組替換開發伺服器的功能:你修改程式碼後,瀏覽器自動更新,無需手動重新整理頁面。底層透過 WebSocket 通知瀏覽器。

總結

連接埠和 localhost 是開發環境中最基礎、最高頻的概念:

  • 連接埠 = 一台機器上區分不同服務的「門牌號」(0–65535)
  • localhost = 「自己找自己」的特殊位址(127.0.0.1),資料不出本機
  • 連接埠衝突的本質是「一個門牌只能掛一塊牌子」
  • 跨域的本質是「連接埠不同 = 不同源」,需要 CORS 或代理來解決

記住這四句話,你在開發環境裡遇到的大多數網路問題,都能快速定位原因。