ipconfig.co.uk

netstat, ss and lsof: ports and connections

ipconfig tells you your address; these tools tell you what is talking on it. The question is nearly always one of three: what is listening, what is connected where, and which program has grabbed port 8080.

The three questions, on each platform

QuestionWindowsLinuxmacOS
What is listening?netstat -ano | findstr LISTENING
Get-NetTCPConnection -State Listen
ss -tulpnlsof -iTCP -sTCP:LISTEN -P -n
netstat -an | grep LISTEN
What is connected, to where?netstat -ano
Get-NetTCPConnection -State Established
ss -tanp state establishedlsof -i -P -n | grep ESTABLISHED
netstat -an | grep ESTABLISHED
What is using port 8080?netstat -ano | findstr :8080 then tasklist /fi "PID eq 1234"ss -tulpn | grep :8080
sudo lsof -i :8080
lsof -i :8080 -P -n

Process names need elevated rights on every platform: run as administrator (netstat -b), or with sudo for ss -p and lsof to see other users' processes.

Windows: netstat

Windows · Command Prompt
netstat -ano                       # all connections and listeners, numeric, with PID
netstat -anob                      # ...plus the executable name (admin)
netstat -ano | findstr LISTENING
netstat -ano | findstr :443
netstat -ano | findstr ESTABLISHED
netstat -ano -p tcp                # TCP only; also udp, tcpv6, udpv6
netstat -e                         # interface byte and packet counters
netstat -e 5                       # refresh every 5 seconds
netstat -s                         # per-protocol statistics (retransmits, errors)
netstat -r                         # routing table, same as route print
netstat -an 2                      # refresh every 2 seconds
Output
  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1092
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:3389           0.0.0.0:0              LISTENING       1240
  TCP    127.0.0.1:8080         0.0.0.0:0              LISTENING       15208
  TCP    192.168.1.42:52114     142.250.187.196:443    ESTABLISHED     7724
  TCP    192.168.1.42:52130     104.16.132.229:443     TIME_WAIT       0
  TCP    [::]:135               [::]:0                 LISTENING       1092
  UDP    0.0.0.0:5353           *:*                                    2456
Local Address 0.0.0.0:445
Listening on port 445 on every IPv4 address, including any the machine may get later. [::]:445 is the same for IPv6. 127.0.0.1:8080 listens only for connections from the machine itself, which is why a development server bound there is not reachable from your phone.
PID 4
The System process: kernel-mode listeners such as SMB (445), HTTP.sys (80/443 when IIS or some apps use it) and RDP support.
PID 0 with TIME_WAIT
A closed connection lingering for a couple of minutes so late packets are discarded safely. Hundreds of these after a busy client session are normal.

Map a PID to a program: tasklist /fi "PID eq 15208", or Task Manager › Details › sort by PID, or Get-Process -Id 15208 | select Name, Path.

PowerShell

Windows · PowerShell
Get-NetTCPConnection -State Listen | Sort-Object LocalPort | Format-Table LocalAddress, LocalPort, OwningProcess
Get-NetTCPConnection -LocalPort 8080
Get-NetTCPConnection -State Established | Select-Object RemoteAddress, RemotePort, @{n='Process';e={(Get-Process -Id $_.OwningProcess).ProcessName}}
Get-NetUDPEndpoint | Sort-Object LocalPort
# one-liner: listening ports with process names
Get-NetTCPConnection -State Listen | ForEach-Object { [pscustomobject]@{ Port=$_.LocalPort; Address=$_.LocalAddress; Process=(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName } } | Sort-Object Port | Format-Table

Reserved port ranges on Windows

If a program fails to bind a port that netstat says is free, Hyper-V or WSL may have reserved a range. netsh interface ipv4 show excludedportrange protocol=tcp lists them. Move the app to another port, or reserve the port explicitly before Hyper-V starts with netsh int ipv4 add excludedportrange protocol=tcp startport=8080 numberofports=1 after temporarily stopping the Hyper-V network service.

Linux: ss

ss ships with iproute2 and replaces netstat, which is in the deprecated net-tools package. The letters are the same.

Linux · Terminal
ss -tulpn                  # TCP and UDP listeners, numeric, with process (sudo for all PIDs)
ss -tanp                   # all TCP with process
ss -tan state established
ss -tan state time-wait | wc -l
ss -tlnp 'sport = :22'     # filter by local port
ss -tanp dst 192.168.1.10  # connections to one host
ss -tanp dport = :443
ss -s                      # summary: totals by state
ss -i                      # TCP internals: rtt, cwnd, retransmits, congestion algorithm
ss -o                      # timers (keepalive, retransmit)
ss -x                      # Unix domain sockets
ss -4tln / ss -6tln        # by address family
watch -n1 'ss -s'          # live counts
Output
$ sudo ss -tulpn
Netid State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp   UNCONN 0      0        127.0.0.53%lo:53        0.0.0.0:*    users:(("systemd-resolve",pid=612,fd=13))
udp   UNCONN 0      0            0.0.0.0:5353      0.0.0.0:*    users:(("avahi-daemon",pid=701,fd=12))
tcp   LISTEN 0      4096       127.0.0.1:631       0.0.0.0:*    users:(("cupsd",pid=889,fd=7))
tcp   LISTEN 0      128          0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=891,fd=3))
tcp   LISTEN 0      511                *:80              *:*    users:(("nginx",pid=1203,fd=6),("nginx",pid=1202,fd=6))
tcp   LISTEN 0      128             [::]:22           [::]:*    users:(("sshd",pid=891,fd=4))
Recv-Q / Send-Q
For listeners: current backlog and its maximum. For connections: bytes not yet read by the application / not yet acknowledged by the peer. A growing Send-Q with a stuck connection means the far end is not reading or the path is black-holed.
127.0.0.53%lo:53
systemd-resolved's stub listener, scoped to the loopback interface. Normal on Ubuntu and Fedora.
*:80
A dual-stack listener on all addresses, both families.

Filter syntax is rich: ss -tan '( dport = :443 or sport = :443 )', ss state connected, ss -tan 'sport >= :1024'. Old-style netstat -tulpn and netstat -anp still work if net-tools is installed.

lsof and fuser on Linux

Linux · Terminal
sudo lsof -i :8080                 # who has port 8080 (listening or connected)
sudo lsof -i -P -n | grep LISTEN
sudo lsof -i tcp:22
sudo lsof -i @192.168.1.10          # connections to a host
sudo fuser 8080/tcp                # just the PID
sudo fuser -k 8080/tcp             # kill it

macOS: lsof and netstat

macOS has no ss, and its netstat cannot show process IDs. lsof is the tool.

macOS · Terminal
lsof -iTCP -sTCP:LISTEN -P -n              # listening TCP ports with process
sudo lsof -iTCP -sTCP:LISTEN -P -n         # including other users' and system processes
lsof -i :8080 -P -n
lsof -i -P -n | grep ESTABLISHED
lsof -iUDP -P -n
netstat -an | grep LISTEN                   # without process info
netstat -anv | grep LISTEN                  # -v adds the PID column on recent macOS
netstat -p tcp -s                           # TCP statistics
netstat -ib                                 # per-interface byte counters
nettop -m tcp                               # live per-process bandwidth (q to quit)
Output
$ lsof -iTCP -sTCP:LISTEN -P -n
COMMAND     PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
rapportd    612 steve    9u  IPv4 0x3a2b     0t0  TCP *:49152 (LISTEN)
ControlCe   640 steve   24u  IPv4 0x3a2c     0t0  TCP *:7000 (LISTEN)
node      15208 steve   21u  IPv6 0x3a2d     0t0  TCP *:8080 (LISTEN)

ControlCenter on ports 5000 and 7000 is AirPlay Receiver, which is what collides with Flask and other dev servers on port 5000; turn it off in System Settings › General › AirDrop & Handoff. rapportd is Continuity. Both are normal.

Connection states

StateMeaningWhen to worry
LISTENA server socket waiting for connectionsOnly if it is a service you did not expect
ESTABLISHEDOpen connection carrying dataNever, unless the remote address is unexpected
SYN_SENTYou sent a connection request, no reply yetMany of these mean the target is unreachable or filtering; a few are normal
SYN_RECV / SYN_RECEIVEDA client sent SYN, you replied, waiting for the final ACKThousands suggest a SYN flood
TIME_WAITYou closed the connection; waiting 60 s (Linux) to 240 s (Windows) for stragglersThousands on a busy server are normal; port exhaustion is possible at tens of thousands
CLOSE_WAITThe peer closed; your application has not yet closed its sideMany that never clear indicate an application leaking sockets
FIN_WAIT_1 / FIN_WAIT_2You closed; waiting for the peer to finishStuck ones mean the peer vanished
LAST_ACKBoth sides closing; waiting for the final ACKRarely
CLOSEDNot in use
UNCONNA UDP socket (ss); UDP has no connections

Freeing a port that is "already in use"

Windows · Command Prompt
netstat -ano | findstr :8080
tasklist /fi "PID eq 15208"
taskkill /PID 15208 /F
Windows · PowerShell
Get-NetTCPConnection -LocalPort 8080 | Select-Object -ExpandProperty OwningProcess | ForEach-Object { Stop-Process -Id $_ -Force }

If the PID is 4 (System), the port is owned by HTTP.sys or a kernel service: netsh http show servicestate lists URL reservations, and netsh http delete urlacl or stopping the World Wide Web Publishing Service releases them. If nothing is listening but binding fails, check the excluded port ranges.

Bandwidth by process

Any shell
nettop -m tcp                              # macOS, built in
sudo iftop -i eth0                         # Linux, by connection
sudo nethogs eth0                          # Linux, by process
Get-Counter '\Process(*)\IO Read Bytes/sec' # Windows, crude; Resource Monitor › Network is easier (resmon)

Related pages

Last reviewed . Command syntax verified against Windows 11, Ubuntu 24.04, macOS 15 and FreeBSD 14 unless noted otherwise.

Spotted a mistake or a switch we have missed? Every page on this site is written to be checked against real output, so please test on your own machine and compare.