Типичная задача: порт занят, кто виноват
При запуске локального сервера или программы иногда появляется сообщение о том, что порт уже используется. Нужно найти, какая программа его заняла: возможно, вы забыли остановить прошлый запуск, а возможно, порт удерживает совсем другая служба. В Windows эту задачу решает связка команд netstat и findstr, а затем tasklist.
Команда netstat -ano выводит все сетевые соединения и слушающие порты. Ключи означают: -a показывать все соединения и слушающие порты, -n числовой вид адресов и портов, -o показать PID процесса-владельца. Вывод получается длинным, поэтому его пропускают через findstr, фильтр по строке. Символ вертикальной черты передаёт вывод одной команды на вход другой.
Все команды выполняются в командной строке. Для просмотра достаточно обычных прав, для показа имени исполняемого файла ключом -b нужны права администратора.
Этот приём пригодится не только разработчикам. Когда игра, сервер мультимедиа или программа удалённого доступа сообщает, что порт недоступен, причина часто в конфликте двух программ. Быстрая проверка через netstat занимает меньше минуты и заменяет переустановку приложения.
Пошаговый поиск по номеру порта
Пример для порта 8080 (пример).
- Выполните netstat -ano | findstr :8080. Двоеточие перед номером снижает риск совпадения с другими числами.
- Найдите строку с состоянием LISTENING: последний столбец содержит PID процесса, например 4312.
- Определите имя программы: tasklist | findstr 4312. Либо точнее: tasklist /fi "PID eq 4312".
- Решите, что делать: закрыть программу штатно, поменять порт в её настройках или завершить процесс.
- При необходимости завершите процесс: taskkill /PID 4312 /F от имени администратора.
Пример вывода (пример):
TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 4312 TCP 192.0.2.10:8080 198.51.100.7:51234 ESTABLISHED 4312
Первая строка означает, что программа слушает порт на всех интерфейсах, вторая показывает конкретное подключённое соединение. PID в обеих строках один и тот же. Чтобы не путать 8080 и, скажем, 18080, в фильтре указывайте двоеточие и пробел: findstr ":8080 ".
Если в выводе нет строк с нужным портом, значит, никто его не слушает, и проблема в другом: например, программа не запустилась или порт ей не нужен. Попробуйте также выполнить команду от администратора, чтобы увидеть больше записей.
Состояния соединений в выводе
В столбце состояния встречаются разные слова, и полезно понимать основные.
| Состояние | Значение |
|---|---|
| LISTENING | Программа ждёт входящих соединений на этом порту |
| ESTABLISHED | Соединение установлено, идёт обмен данными |
| TIME_WAIT | Соединение закрыто, система ещё удерживает его некоторое время |
| CLOSE_WAIT | Другая сторона закрыла соединение, а программа ещё не закрыла свою сторону |
| SYN_SENT | Идёт попытка установить исходящее соединение |
Для поиска занятого порта важно состояние LISTENING: именно оно блокирует запуск другой программы на том же порту. Записи TIME_WAIT после остановки сервера могут ещё некоторое время присутствовать, но на новый запуск они обычно не влияют. Множество записей CLOSE_WAIT у одной программы намекает на ошибку в её коде: соединения не закрываются.
Для UDP строки выглядят иначе: нет состояния, есть только локальный адрес и PID.
Если состояний TIME_WAIT очень много, это обычно признак частых коротких соединений, например у веб-клиента. Само по себе это не ошибка. Тревогу стоит бить, когда система исчерпывает доступные локальные порты и новые соединения перестают устанавливаться.
Вариант в PowerShell
PowerShell предлагает более удобный способ без разбора текста. Команда Get-NetTCPConnection -LocalPort 8080 выводит соединения на порту вместе со столбцом OwningProcess, это тот же PID. Имя процесса получают командой Get-Process -Id 4312.
Объединить шаги можно в одну строку (пример): Get-Process -Id (Get-NetTCPConnection -LocalPort 8080 -State Listen).OwningProcess. Команда вернёт объект процесса с именем и другими сведениями. Для UDP служит Get-NetUDPEndpoint с тем же параметром порта.
Преимущество PowerShell в том, что вывод структурирован и не зависит от языка системы, а строки netstat приходится разбирать вручную. Недостаток в более громоздком синтаксисе для быстрых проверок, поэтому в повседневной работе часто хватает связки netstat и findstr.
Если нужно посмотреть исполняемый файл, в командной строке от администратора выполните netstat -ab, но вывод будет медленнее.
При разборе больших объёмов вывода PowerShell удобнее: результаты можно отсортировать по состоянию или сгруппировать по процессам. Например, Get-NetTCPConnection | Group-Object State покажет, сколько соединений находится в каждом состоянии, а это быстро выявляет подозрительные скопления.
Когда завершать процесс нельзя или не нужно
Не всякий процесс стоит убивать. Перед taskkill убедитесь, что понимаете, что это за программа.
- PID 4 (System) и процессы, связанные со службами Windows, завершать нельзя: порт занимает системный драйвер, а не приложение. Часто это службы, встроенные в систему.
- Порт может быть зарезервирован системой без активной программы. Диапазоны исключённых портов показывает команда netsh int ipv4 show excludedportrange protocol=tcp: порт из этого списка занять нельзя, нужно выбрать другой.
- Если процесс принадлежит нужной вам программе, закройте её штатно, а не принудительно, чтобы избежать потери данных.
- Незнакомый процесс на неожиданном порту повод проверить систему антивирусом и разобраться, откуда он взялся, а не просто завершить.
Для удалённой диагностики другой машины вам потребуется разрешение владельца. Проверяйте порты своих компьютеров. Рекомендации по смене порта у вашей программы ищите в её настройках: чаще всего проще изменить порт, чем воевать с занявшим его процессом.
Если порт нужен программе постоянно, а его занимает другая служба, лучший выход изменить порт у одной из них. Настройка порта есть практически в каждой программе, в конфигурационном файле или в параметрах запуска, и после смены достаточно перезапустить приложение и снова проверить порт командой.