定位 connect() 抛 connectexception 需逐层排查:先 telnet/nc 测试 tcp 连通性;不通则查本地防火墙、目标 iptables/ufw、云安全组;若本地连 localhost 通而局域网 ip 不通,大概率服务绑定 127.0.0.1 而非 0.0.0.0;java 中显式调用 socket.connect(addr, timeout) 才能控制握手超时,dns 失败抛 unknownhostexception 且发生在 connect 前。

Socket 连接建立失败时,connect() 抛 java.net.ConnectException 怎么定位?
不是端口没开就是路由不通,但具体卡在哪一层得一层层筛。先确认目标服务真在运行:telnet host port 或 nc -zv host port 能通,说明 TCP 层没问题;如果连不通,再看本地防火墙、目标机器的 iptables / ufw、云服务器安全组——这些比代码更常背锅。
常见错误现象:本地开发连 localhost:8080 没问题,一换 192.168.x.x 就超时。大概率是服务绑定到了 127.0.0.1(比如 Spring Boot 默认),而非 0.0.0.0。检查服务启动日志里 bind 地址,别只信配置文件。
- Java 侧用
Socket构造器直接传地址和端口,会隐式调用connect(),超时由系统默认 socket timeout 控制(通常很长,可能几分钟) - 显式调用
socket.connect(new InetSocketAddress(host, port), timeoutMs)才能控制连接阶段超时,这个 timeout 是纯 TCP 握手耗时,不包含 DNS 解析 - DNS 解析失败会抛
UnknownHostException,它发生在connect()前,别混在一起排查
为什么 InputStream.read() 会一直阻塞,而不是立刻返回 -1?
因为 TCP 是流式协议,-1 只在对端调用 close() 或 shutdownOutput() 后才出现,表示“对方不会再发数据了”。只要连接还开着,哪怕对方发完就干坐着,你的 read() 仍会等下去。
使用场景很典型:HTTP 客户端自己写 socket 读响应体,但没按 Content-Length 或 chunked 规则解析,就傻等 EOF。
立即学习“Java免费学习笔记(深入)”;
- 不要用
read()单字节循环等 -1,性能差还容易卡死 - 优先用
read(byte[] b, int off, int len),配合已知报文长度或协议分隔符(如\r\n\r\n) - 真需要检测连接断开,得靠
setSoTimeout()配合异常捕获,而不是依赖read()返回值
ServerSocket.accept() 返回的 Socket 和原始 ServerSocket 的 SO_TIMEOUT 有关系吗?
没关系。ServerSocket.setSoTimeout() 只影响 accept() 调用本身的阻塞时长;一旦 accept() 返回新 Socket 实例,它的超时、缓冲区大小、Nagle 算法等所有 socket 选项都得单独设置。
容易踩的坑:给 ServerSocket 设置了 soTimeout=5000,以为子 socket 也自动继承,结果读请求时无限等待。
- 新建的
Socket默认soTimeout = 0(阻塞到底) - 必须显式调用
clientSocket.setSoTimeout(30000)才能控制读写超时 -
setTcpNoDelay(true)建议开启,避免 Nagle 算法攒小包,对交互式协议(如自定义 RPC)影响明显
Java 里用 Socket 发送中文,对方收到乱码,是不是编码没设对?
八成是没设,但错不在 Socket 本身——它只管发字节。乱码根源在字符串转字节这一步:你用 "你好".getBytes(),用的是平台默认编码(Windows 是 GBK,Linux/macOS 通常是 UTF-8),而接收方按固定编码(比如 UTF-8)解,自然对不上。
参数差异直接决定表现:"你好".getBytes(StandardCharsets.UTF_8) 和 "你好".getBytes("UTF-8") 看似一样,但后者抛 UnsupportedEncodingException,前者不会。
- 发送前统一用
str.getBytes(StandardCharsets.UTF_8) - 接收方用
new String(bytes, StandardCharsets.UTF_8)解码 - 协议里最好带个编码声明字段(比如 HTTP 的
Content-Type: text/plain; charset=utf-8),别让双方猜
TCP 连接本身不维护字符概念,所有关于“中文”“乱码”的问题,本质都是字节序列解释权没对齐。这点比线程安全还容易被忽略。











