最常用方式是直接用构造方法绑定端口,如new ServerSocket(8080),会立即绑定到0.0.0.0:8080并监听;端口占用或权限不足(1–1023端口需root)将抛出BindException;设为0则自动分配临时端口;显式bind()更灵活,支持地址限定、端口复用等;backlog指定已完成握手但未accept的连接队列长度,默认50。

直接用 ServerSocket 构造方法绑定端口最常用,但要注意底层行为和常见陷阱。
构造时绑定是最简洁的方式
写法如:new ServerSocket(8080)。这行代码会立即尝试将服务绑定到本机所有网卡的 8080 端口(即 0.0.0.0:8080),并开始监听。
- 如果端口已被占用,会立刻抛出 BindException(属于
IOException),错误信息类似Address already in use - 若指定端口为 1–1023,非 root/Admin 权限下会因权限不足而失败
- 端口号设为 0,系统会自动分配一个可用临时端口,适合需要动态端口的场景(如测试)
显式调用 bind() 方法更灵活
适用于需控制绑定地址、复用端口或延迟绑定的场景:
- 先创建未绑定实例:
ServerSocket ss = new ServerSocket() - 设置端口复用(避免
TIME_WAIT占用):ss.setReuseAddress(true) - 构造地址对象,例如只允许本地访问:
InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8080) - 执行绑定:
ss.bind(addr)
这种方式能明确区分“创建 socket”和“绑定资源”两个阶段,便于异常分类处理和配置化管理。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
绑定后必须用 accept() 进入监听循环
accept() 是阻塞方法,它不主动轮询,而是等待操作系统通知有已完成三次握手的连接就绪。
- 每次调用返回一个
Socket对象,代表与单个客户端的专属通信通道 - 若想优雅关闭,不能只靠
Thread.interrupt();必须在关闭逻辑中先调用ss.close(),它会让阻塞中的accept()立即抛出SocketException: Socket closed - 建议在循环中加判断:
if (ss.isClosed()) break;,防止 close 后继续调用 accept
backlog 参数影响连接排队能力
构造时可指定:new ServerSocket(8080, 100)。这个 100 不是最大并发数,而是内核中“已完成握手、等待你调用 accept() 取走”的连接队列长度。
- 默认值通常为 50,高并发短连接场景建议设为 100–200
- 超过 backlog 的新连接会被内核直接拒绝(客户端收到 RST 包),不是等待或超时
- 该值受系统限制(如 Linux 的
net.core.somaxconn),设得过大无实际效果


















