端口冲突通常发生在尝试运行两个或多个应用程序或服务时,它们尝试
使用同一个端口号,导致系统无法正确分配资源。
各种端口错误
你是否遇到过下面这些报错信息呢?
Windows 系统报错:
1
2系统错误 1004
套接字操作尝试使用一个已由另一个进程或服务占用的端口。Windows 系统命令提示符报错:
1
2The requested address is not available.
Java 程序运行时报错:
1
java.net.BindException: Address already in use: local port 8080
Apache HTTP 服务器报错:
1
AH00526: Syntax error on line 287: Could not bind to address 0.0.0.0:80 - Address already in use
Nginx 报错:
1
listen 80 failed (98: Address already in use)
MySQL 报错:
1
[Warning] Failed to start slave; MySQL error: 1130 - Host 'host' is not allowed to connect to this MySQL server
Windows 服务管理器报错:
1
The service did not start due to a logon failure.
SpringBoot 工程启动报错:
1
Web server failed to start. Port 8080 was already in use.
解决方案
1.Windows
- **查看占用端口的PID
1
2
3
4
5假设我现在3000端口被占用
netstat -ano | findstr 3000
得到最后一个就是PID,也就是`18576`
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 18576 - 查询运行程序:
1
2
3
4
5根据PID,也就是上面得到的`18576`
tasklist | findstr 18576
得到第一个就是应用程序名,也就是`node.exe`
node.exe 18576 Console 10 147,444 K如果此时你认识这个应用,并且它可以关闭,直接进入最后
杀死进程阶段,如果你不确定,继续下一步 - 查询程序路径
1
2
3
4
5根据应用名,也就是上面得到的`node.exe`
wmic process where name="node.exe" get processid,executablepath
得到第一个就是应用程序路径,第二个就是就是`PID`
D:\Downloads\nodejs\node.exe 18576 - 命令杀死进程
1
2根据PID,也就是上面得到的`18576`
taskkill -PID 18576 -F - 任务管理器杀死进程

2. Linux
1 | 查端口 |
3. SpringBoot解决
在你的配置文件中
1 | server |
有没有可能让springboot自己检查端口是否别占用呢?并且给我们更换到可用端口呢?
当然实际不要这么做,上线后端口需要固定,这只是一个锻炼思维的一个demo
maven导包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version> <!-- 使用最新版或适合你项目的版本 -->
<scope>provided</scope> <!-- 在编译时添加,运行时不需要 -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version> <!-- 使用最新版或适合你项目的版本 -->
</dependency>
</dependencies>application.yml
1
2
3
4
5
6
7server:
port: 3000 #配置你的端口
sdk:
port:
retry-count: 10 #尝试重试次数
max-port: 10000 #最大端口数
min-port: 1000 #最小端口数配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Random;
/**
* @ Author:Yang
* @ Description:自动加载可用端口配置
* @ create:2024-10-06-13:54
*/
public class PortAutoConfiguration {
private int defaultPort;
private int retryCount;
private int maxPort;
private int minPort;
public TomcatConnectorCustomizer customServerPortTomcatConnectorCustomizer() {
// 尝试次数为0,则设置为0
if (retryCount < 0) retryCount = 0;
// 确保最大端口不小于最小端口
if (maxPort < minPort) maxPort = minPort;
// 从默认端口开始寻找可用端口
int port = findAvailablePort(defaultPort);
log.info("设置端口为 port : {}", port);
// 返回可用端口
return connector -> connector.setPort(port);
}
private int findAvailablePort(int port) {
Random random = new Random();
//已经尝试次数
int count = 0;
// 这样可以保证最小为 1 ,random的最小为0
int bound = maxPort - minPort + 1;
while (count < retryCount) {
try (ServerSocket serverSocket = new ServerSocket(port)) {
return port;
} catch (IOException e) {
// 端口被占用,尝试下一个端口
int oldPort = port;
count++;
port = minPort + random.nextInt(bound);
log.warn("{}端口冲突,更换端口为{},已尝试{}次",oldPort,port,count);
}
}
// 如果循环结束后仍未找到可用端口,抛出异常或返回特定值
throw new RuntimeException("Unable to find an available port after " + retryCount + " retries");
}
}运行结果
成功更换
