serversocket构造时端口被占用直接抛bindexception;accept()阻塞需close()才能响应中断;绑定0.0.0.0接受所有网卡连接,127.0.0.1仅限本地;backlog是已完成握手的等待队列长度,非并发上限。

ServerSocket 构造时端口被占用会抛什么异常
直接抛 IOException,常见具体子类是 BindException,错误信息类似 java.net.BindException: Address already in use。这不是运行时逻辑错误,而是系统级资源冲突——端口正被其他进程(如另一个 Java 进程、nginx、甚至残留的 zombie 进程)监听。
实操建议:
- 启动前用命令查端口:Linux/macOS 执行
lsof -i :8080或netstat -an | grep 8080;Windows 用netstat -ano | findstr :8080 - 代码里加 try-catch 捕获
BindException,别只 catchIOException,否则容易掩盖真实原因 - 避免硬编码端口,改用配置或命令行参数,方便测试时快速换端口
accept() 阻塞期间能否响应中断
能,但必须配合 Thread.interrupt() 和 isClosed() 判断。单纯调用 interrupt() 不会唤醒阻塞中的 accept(),除非你先调用 serverSocket.close() —— 这会强制触发 SocketException: Socket closed。
常见错误现象:线程调用 interrupt() 后仍卡在 accept(),因为没关 socket。
实操建议:
- 关闭服务器时,优先调用
serverSocket.close(),再清理线程 - 在
accept()外层加if (serverSocket.isClosed()) break;,防止 close 后继续循环 - 不要依赖
Thread.interrupted()判断 accept 是否该退出,它对阻塞 I/O 无效
绑定 0.0.0.0 和 127.0.0.1 的区别是什么
new ServerSocket(8080) 默认绑定 0.0.0.0,表示接受所有网卡(包括公网 IP)的连接;显式指定 new ServerSocket(8080, 50, InetAddress.getByName("127.0.0.1")) 则只响应本地回环请求,外部机器无法访问。
使用场景:
- 开发调试用
127.0.0.1更安全,避免意外暴露服务 - 生产部署若需外网访问,必须确保绑定的是
0.0.0.0或具体公网 IP,且防火墙放行该端口 - 某些云环境(如 Docker)中,
localhost在容器内指向容器自身,不等于宿主机,此时用0.0.0.0才能被外部访问
设置 backlog 参数的实际影响
ServerSocket(int port, int backlog) 中的 backlog 控制的是**已完成三次握手、等待 accept() 取走的连接队列长度**,不是最大并发数。Linux 默认是 50,超过后新连接会直接被内核拒绝(客户端收到 RST)。
性能影响:
- 值太小(如 1):高并发下容易丢连接,尤其当业务线程处理
accept()较慢时 - 值太大(如 10000):不提升吞吐,反而浪费内核内存;实际有效上限受系统
net.core.somaxconn限制 - Java 8+ 中,若传入负数或 0,会自动取系统默认值,不必硬写 50
真正控制并发能力的是后续如何处理 Socket:用线程池还是 NIO,是否及时关闭流,这些比 backlog 关键得多。
ServerSocket 使用链路。最容易被忽略的是 close() 对 interrupt() 的协同作用,以及 backlog 并不等于并发上限这个事实。










