Skip to content

Ports and localhost

💡 Learning Guide: When you run npm run dev and the terminal shows http://localhost:5173, have you ever wondered: what is localhost? What does 5173 represent? Why do you sometimes get an EADDRINUSE error? This chapter will thoroughly explain these concepts you see every day in development but rarely dig into.

Before we begin, it's recommended to brush up on two foundational topics:


0. Introduction: What Exactly Is That localhost:5173 You See Every Day?

1
2
3
4
5
1. 你执行 npm run dev
终端
$ npm run dev

> vite

  准备就绪...
监听
浏览器
等待你打开浏览器...
💡 你在终端里敲下启动命令
什么是 HTTP 服务器?
🏪
想象一个前台窗口HTTP 服务器就像一个"永远开着的服务窗口"——它一直等在那里,有人来问就回答,没人来就静静等着。
📋
只懂一种"暗号"这个窗口只听得懂 HTTP 协议的请求格式(比如 GET /index.html),然后把对应的文件内容返回给你。
⚙️
开发服务器 = 加强版窗口Vite、Webpack 的开发服务器不只是"原样返回文件",它还会即时编译你的代码(Vue → JS、TS → JS、Sass → CSS),然后再返回给浏览器。
一句话总结:开发服务器 = 一个运行在 localhost 上的 HTTP 服务器 + 即时代码编译器。它监听某个端口,浏览器来请求,它就把编译好的代码返回。

Every developer's daily routine includes this line of output:

➜  Local:   http://localhost:5173/

But have you ever thought about how many key concepts are packed into this short line:

  • http:// → The communication protocol (what language to speak)
  • localhost → The target address (who to find)
  • :5173 → The port number (which door to knock on after finding the address)

Understand these three things, and you'll be able to figure out 90% of development environment networking issues. Let's break them down one by one.


1. What Is a Port? (IP Is the Building, Port Is the Room Number)

1.1 An Intuitive Analogy

Imagine a server is a building:

  • An IP address (e.g., 192.168.1.100) is the building's street address — it tells you "which building to go to."
  • A port number (e.g., :80) is the room number inside the building — it tells you "which room to enter."

A building can simultaneously have a restaurant (room 80), a cafe (room 443), and an office (room 22). Similarly, a single computer can run a web server, a database, and an SSH service simultaneously, each using a different port.

👇 Try it out: Click the "room numbers" below to simulate connecting to different ports. Notice what happens when a port is "open" (a program is listening) versus "closed."

选择一栋"大楼":
Web 服务器大楼IP: 192.168.1.100
80
HTTP网页访问入口
🟢 监听中
443
HTTPS加密网页入口
🟢 监听中
22
SSH远程管理通道
🟢 监听中
3306
MySQL数据库(已关闭)
🔴 已关闭
核心比喻:IP 地址 = 大楼地址,端口号 = 房间门牌号。一台电脑上可以同时运行多个服务,每个服务"占用"一个端口号,就像同一栋大楼里的不同房间。

1.2 Port Number Ranges

A port number is an integer between 0–65535 (65,536 total). These ports are divided into three ranges:

RangeValuesPurposeExamples
System Ports0 – 1023Reserved for standard protocols; ordinary users can't freely use them80 (HTTP), 443 (HTTPS), 22 (SSH)
Registered Ports1024 – 49151Registered for common applications3306 (MySQL), 5432 (PostgreSQL), 6379 (Redis)
Dynamic Ports49152 – 65535Temporarily assigned by the operating systemWhen a browser makes a request, the OS randomly assigns a source port

Why does your dev server like to use 3000, 5173, or 8080? Because they're all in the "registered ports" range — no admin privileges needed to listen on them, and they're less likely to conflict with system services.

1.3 Common Port Numbers in Development

👇 Try it out: Enter a port number or service name to search. Click any row to expand and see usage examples.

端口服务说明暴露风险
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
系统端口预留给标准服务(HTTP、SSH 等),普通用户不能随便占用。
1024 – 49151
注册端口留给常见应用(MySQL 3306、Redis 6379 等),开发中最常遇到的范围。
49152 – 65535
动态端口操作系统临时分配的端口,比如你的浏览器发请求时,系统会随机给你一个。
安全提醒:数据库端口(3306、5432、27017、6379)绝对不要直接暴露到公网!生产环境应只允许内网访问或通过 SSH 隧道连接。

2. What Is localhost? (Finding Yourself)

2.1 The Core Concept of "Loopback"

localhost is a special domain name that always points to your own computer.

When you type http://localhost:3000 in your browser, here's what happens:

  1. The browser asks the OS: "What's the IP for localhost?"
  2. The OS answers directly: "127.0.0.1" (no need to look up DNS over the network)
  3. The packet is sent to 127.0.0.1, but never actually leaves your machine
  4. The OS "loops back" the packet through the loopback interface
  5. The program listening on port 3000 receives the request and sends a response

The entire process doesn't go through any network cable, router, or internet connection.

👇 Try it out: Click "Send Request" to observe the complete journey of a data packet. Then click the "alias cards" below to learn about the different ways to write localhost and their differences.

🔗
🌐
浏览器你在地址栏输入 URL
📖
DNS 解析localhost → 127.0.0.1(不出网)
🔄
网络层数据包发往 127.0.0.1(环回接口)
⚙️
本机服务端口 3000 上的程序接收请求
📨
返回响应{ "message": "Hello!" }
你的应用(浏览器)
请求不离开本机
本地服务(:3000)
localhost 的"马甲"们(点击查看说明)
localhost→ 127.0.0.1
127.0.0.1→ 127.0.0.1
::1→ ::1
0.0.0.0→ 0.0.0.0
这是写在你电脑 <code>/etc/hosts</code> 文件里的映射。浏览器看到 <code>localhost</code> 时,直接解析为 <code>127.0.0.1</code>,不会去问 DNS 服务器。: 这是写在你电脑 /etc/hosts 文件里的映射。浏览器看到 localhost 时,直接解析为 127.0.0.1,不会去问 DNS 服务器。
核心概念:localhost 就是"自己找自己"。数据包通过环回接口(loopback interface)在本机内部折返,不经过网线、不经过路由器,速度极快且完全安全。

2.2 localhost vs 127.0.0.1 vs 0.0.0.0

These three concepts are often confused, but they mean entirely different things:

NotationMeaningWho Can Access
localhost / 127.0.0.1Loopback address, local machine onlyOnly your own computer
0.0.0.0Listen on all network interfacesLocal machine + other devices on the LAN
192.168.x.xLAN IPDevices on the local network

Practical scenarios:

bash
# Only you can access (secure, good for development)
npm run dev -- --host localhost

# Your phone can also access (good for mobile debugging)
npm run dev -- --host 0.0.0.0

Many frameworks (like Vite, Next.js) listen on localhost by default, so even if your phone is on the same WiFi, it can't access your dev server. Want to debug on mobile? Just add the --host flag.


3. Port Conflicts: The Most Common Dev Environment Issue

3.1 Why Do Conflicts Happen?

One port can only be listened on by one program at a time. It's like one room can only house one family.

If you try to start a second service on the same port, you'll see this classic error:

Error: listen EADDRINUSE :::3000

In plain English: "Room 3000 is already occupied — you can't get in!"

Common conflict scenarios:

  • The previous dev server wasn't properly shut down and is still running in the background
  • Two different projects use the same default port
  • Some system service has already taken the port you want

👇 Try it out: Try starting services multiple times in the simulator below. When a port conflict occurs, compare how "direct start" and "smart start" handle it differently.

尝试启动:React(默认端口 5173)
当前运行的服务1 个
Vite:5173🟢 运行中
端口冲突:一个端口同一时刻只能被一个程序监听。如果你看到 EADDRINUSE 错误,说明这个端口已经被占了。要么杀掉旧进程,要么换个端口。

3.2 Troubleshooting and Resolution

When you encounter a port conflict, the troubleshooting steps are very consistent:

macOS / Linux:

bash
# Step 1: Check who is using port 3000
lsof -i :3000

# Step 2: Once you have the PID, force kill it
kill -9 <PID>

Windows:

bash
# Step 1: Check who is using port 3000
netstat -ano | findstr :3000

# Step 2: Kill the process
taskkill /PID <PID> /F

Many modern frameworks (Vite, Create React App, etc.) will automatically ask "switch to another port?" when they detect a conflict. But understanding the underlying principles helps you troubleshoot those tricky issues that frameworks can't handle.


4. Same-Origin Policy and CORS in Development

4.1 What Is an "Origin"?

Browsers have a security mechanism called the Same-Origin Policy: only when the protocol, domain, and port are all identical, are two URLs considered the "same origin."

URL AURL BSame Origin?Reason
http://localhost:5173http://localhost:5173/about✅ Same originProtocol, domain, port are all the same
http://localhost:5173http://localhost:3000❌ Different originDifferent ports (5173 vs 3000)
http://localhost:5173https://localhost:5173❌ Different originDifferent protocols (http vs https)

4.2 Why Does Frontend-Backend Separation Always Encounter CORS?

When your project architecture is:

Frontend (Vite)  →  http://localhost:5173
Backend (Express) →  http://localhost:3000

The frontend page loads from :5173, then uses fetch('/api/users') to request the API on :3000different ports trigger the cross-origin restriction!

Two common solutions:

Option 1: Configure CORS on the backend

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

Option 2: Configure a proxy on the frontend (recommended)

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

How the proxy works: The Vite dev server "forwards" requests on your behalf. The browser thinks it's communicating with :5173 (same origin), while Vite secretly relays the requests to :3000 behind the scenes.


5. Practical Troubleshooting: Three Most Common Issues

👇 Try it out: Select an issue you've encountered, and follow the steps to troubleshoot. Click "Execute" on each step to see the output.

选择一个常见问题:
🔴
端口被占用Error: listen EADDRINUSE :::3000
排查步骤 (1/3)
$lsof -i :3000
查看谁在用这个端口
排查口诀:先确认服务有没有启动(lsof / netstat),再确认端口对不对,最后确认是不是跨域问题。90% 的 localhost 问题都逃不出这三步。

6. Terminology Reference

English TermChinese TranslationExplanation
Port端口A number from 0–65535 used to distinguish different network services on the same machine. Each service "listens" on a port, waiting for client connections.
localhost本地主机A special domain name that always points to the local machine (127.0.0.1). Used to access services running on your own machine without an internet connection.
Loopback Interface环回接口A virtual network interface in the operating system. Packets sent to 127.0.0.1 never leave the machine; they are "looped back" through this interface.
EADDRINUSE地址已被使用An error from Node.js / the OS indicating the port you want to listen on is already occupied by another program.
CORS跨域资源共享A browser security mechanism. When a frontend page tries to request an API from a different origin (different protocol/domain/port), the backend must explicitly grant permission.
Same-Origin Policy同源策略The cornerstone of browser security: only allows free communication between requests with the same protocol, domain, and port, blocking cross-origin data reads.
Proxy代理In a dev environment, a proxy server forwards requests from the browser to the backend, bypassing the browser's same-origin restriction.
0.0.0.0所有接口When a service listens on 0.0.0.0, it accepts connections from any network interface (local machine, LAN, etc.).
Well-known Ports知名端口The collective name for ports 0–1023, reserved for standard protocols like HTTP (80), HTTPS (443), SSH (22).
PID进程 IDA unique number assigned by the OS to each running program, used to manage and terminate processes.
lsof列出打开的文件A macOS/Linux command used to see which process is using a specific port (lsof -i :port_number).
HMR热模块替换A dev server feature: when you modify code, the browser updates automatically without manual refresh. Works via WebSocket notifications under the hood.

Summary

Ports and localhost are the most fundamental, most frequently encountered concepts in the development environment:

  • Port = A "room number" distinguishing different services on a machine (0–65535)
  • localhost = The special "find yourself" address (127.0.0.1), data never leaves your machine
  • Port conflict is essentially "one room number can only have one sign"
  • CORS is essentially "different ports = different origins," requiring CORS or a proxy to resolve

Remember these four points, and you'll be able to quickly identify the cause of most networking issues in your development environment.