A network port is a 16-bit number (0-65535) that identifies a specific process or service on a computer.
When data arrives at a computer via its IP address, the port number tells the operating system which application should receive that data.
Analogy: Think of an IP address as a building's street address, and the port number as the apartment number within that building. The mail carrier (network packets) needs both to deliver to the right recipient.
When you connect to a website, your computer uses multiple pieces of information:
Client Computer (192.168.1.100) Server Computer (93.184.216.34)
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ │ │ │
│ Browser (Port 54321) ◄──────┼────────────┼──────► Port 443 (HTTPS) │
│ │ Internet │ │
│ Node.js App (Port 62345) ◄──┼────────────┼──────► Port 3306 (MySQL) │
│ │ │ │
│ Multiple apps can send │ │ Each port serves one │
│ from different ports │ │ application/service │
└──────────────────────────────┘ └──────────────────────────────┘
Your computer uses dynamic/ephemeral ports (like 54321, 62345) for outbound connections
Servers listen on specific well-known ports (like 443, 3306) for incoming connections
The Internet Assigned Numbers Authority (IANA) divides the 65,536 ports into three categories:
| Range | Category | Description | Examples |
|---|---|---|---|
| 0-1023 | Well-Known Ports | Reserved for common services. Requires admin/root privileges to bind. | HTTP (80), HTTPS (443), SSH (22), FTP (21), SMTP (25) |
| 1024-49151 | Registered Ports | Registered with IANA for specific services. Commonly used by applications. | MySQL (3306), PostgreSQL (5432), MongoDB (27017), Redis (6379) |
| 49152-65535 | Dynamic/Private Ports | Available for any application. Used for ephemeral (temporary) connections. | Randomly assigned by OS for outbound connections |
These ports are assigned to fundamental internet services. On Unix-like systems (Linux, macOS), binding to these ports requires root/administrator privileges.
These ports are registered with IANA but don't require special privileges. This is where most development tools and databases listen.
When your browser or application makes an outbound connection, the OS assigns a random port from this range. These are called ephemeral ports and are automatically managed by the operating system.
# See your ephemeral port range (Linux) cat /proc/sys/net/ipv4/ip_local_port_range # Output: 32768 61000 # See active connections with ephemeral ports netstat -an | grep ESTABLISHED # You'll see your computer using ports like 54321, 58234, etc.
Ports exist for both TCP (Transmission Control Protocol) and UDP (User Datagram Protocol). The same port number on TCP and UDP are completely separate - a service can listen on TCP 80 and UDP 80 simultaneously.
Different frameworks and tools have conventional default ports. While you can change these, using standard ports helps with documentation and onboarding.
Only ONE process can bind to a specific IP:Port:Protocol combination at a time.
This means:
The most common port error is EADDRINUSE: address already in use. This happens when you try to bind to a port that's already bound.
Error: listen EADDRINUSE: address already in use :::3000
at Server.setupListenHandle [as _listen2] (net.js:1318:16)
at listenInCluster (net.js:1366:12)
at Server.listen (net.js:1452:7)
events.js:292
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE :::3000
How to fix: Find what's using the port and kill it, or use a different port.
// ✅ Good: Configurable port with sensible default const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); // ❌ Bad: Hardcoded port app.listen(3000, () => { console.log('Server running on port 3000'); });
Port forwarding (also called port mapping) redirects network traffic from one port to another. This is essential for:
Forward external port to internal machine:
Internet → Router:8080 → Forward to → 192.168.1.100:3000
(Public IP) (Your Computer)
Example: Friend accessing your local server
Friend types: http://your-public-ip:8080
Router forwards to: http://192.168.1.100:3000
# Forward remote server's port 5432 to your localhost:5432 ssh -L 5432:localhost:5432 [email protected] # Now you can connect to remote PostgreSQL as if it's local: psql -h localhost -p 5432 -U postgres
# Map container port 3000 to host port 3000 docker run -p 3000:3000 my-node-app # Map host 8080 to container 3000 docker run -p 8080:3000 my-node-app # Format: -p HOST_PORT:CONTAINER_PORT
# macOS / Linux # Show process using port 3000 lsof -i :3000 # Alternative: netstat (older but widely available) netstat -tuln | grep 3000 # Modern Linux: ss command ss -tuln | grep 3000 # Show all listening ports lsof -i -P | grep LISTEN
# Windows # Find process using port 3000 netstat -ano | findstr :3000 # Output shows PID in last column: # TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 12345 # Find process name by PID tasklist | findstr "12345" # PowerShell: More detailed info Get-NetTCPConnection -LocalPort 3000 | Select-Object -Property LocalPort, OwningProcess
# macOS / Linux # Kill by PID (get PID from lsof output) kill -9 12345 # One-liner: Find and kill process on port 3000 lsof -ti:3000 | xargs kill -9 # Using npx kill-port (cross-platform Node.js tool) npx kill-port 3000
# Windows # Kill by PID taskkill /PID 12345 /F # Kill all Node.js processes (use with caution!) taskkill /IM node.exe /F # PowerShell: Kill process on port 3000 Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess | Stop-Process -Force
# Try to connect to see if port is open # macOS / Linux nc -zv localhost 3000 # Output: "Connection refused" = port is available # Output: "succeeded!" = port is in use # Alternative: telnet telnet localhost 3000 # Alternative: curl curl http://localhost:3000
# Windows PowerShell Test-NetConnection -ComputerName localhost -Port 3000 # Check multiple ports 3000,3001,3002 | ForEach-Object { Test-NetConnection -ComputerName localhost -Port $_ -WarningAction SilentlyContinue }
A: Technically yes, but you'll need admin/root privileges. It's better to use 3000, 8000, or 8080 for development and configure your production server (Nginx, Apache) to proxy port 80 to your app's port.
A: Your app might be binding to a specific interface. If it binds to 127.0.0.1, only that address works. If it binds to 0.0.0.0, both localhost and 127.0.0.1 work. Check your app's listen configuration.
A: The protocol determines the default port: HTTP → 80, HTTPS → 443, FTP → 21, SSH → 22. When you type https://google.com you're actually connecting to https://google.com:443.
A: Yes! Each container has its own network namespace. Two containers can both run services on port 3000 internally. However, you can't map both to the same host port (both -p 3000:3000 would fail). Use -p 3000:3000 and -p 3001:3000.
A: 0.0.0.0:3000 (all interfaces) - server accepts connections from anywhere (localhost, LAN, internet if firewall allows). 127.0.0.1:3000 (loopback only) - server only accepts connections from the same machine. Use 127.0.0.1 for security, 0.0.0.0 for accessibility.
A: Microservices and container orchestration often deploy multiple instances on sequential ports. Instead of opening 100 individual ports, you can open a range. Docker Swarm and Kubernetes use this pattern.
man 7 tcp and man 7 udp in terminal