客户端Socket创建失败(ConnectException):跨机器单向连接异常
单向Socket连接失败排查问题
环境与代码
主机信息
- 两台主机:
q2(IP:10.90.50.101)、w18(IP:10.90.50.102) - 共用
file.cfg文件存储Socket通信依赖的IP地址
Client代码
public class Client { public static void main(String... C) { try { String filePath = "file.cfg"; String ip = ""; byte[] bytes = Files.readAllBytes(Paths.get(filePath)); ip = new String(bytes); ip = ip.trim(); System.out.println("cfg file contains " + ip); Socket so = new Socket(ip, 3112); System.out.println("socket Connected. " + so.toString()); so.setSoTimeout(30000); BufferedReader reader = new BufferedReader( new InputStreamReader(so.getInputStream(), StandardCharsets.UTF_8)); System.out.println(reader.readLine()); } catch (Exception e) { e.printStackTrace(); } } }
Server代码
public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = null; try { String filePath = "file.cfg"; String ip = ""; byte[] bytes = Files.readAllBytes(Paths.get(filePath)); ip = new String(bytes); ip = ip.trim(); System.out.println("cfg file contains" + ip); serverSocket = new ServerSocket(3112, 50, InetAddress.getByName(ip)); System.out.println("Server Socket is created. " + serverSocket.toString()); } catch (IOException ex) { ex.printStackTrace(); } Socket socket = null; try { System.out.println("Waiting for Accept..."); socket = serverSocket.accept(); System.out.println("Accepted..."); OutputStreamWriter localOut = new OutputStreamWriter(socket.getOutputStream()); localOut.write("Hi,"); localOut.write("Hello"); localOut.write("\n"); localOut.flush(); localOut.close(); } catch (Exception ex) { ex.printStackTrace(); } socket.close(); serverSocket.close(); } }
file.cfg内容
10.90.50.101 # this ip will be similar in both machines # for ref, # 10.90.50.101 -> q2 and # 10.90.50.102 -> w18
测试场景
成功场景
- 在
w18上同时运行Client和Server,运行正常 - 在
q2上同时运行Client和Server,运行正常 - 在
q2上运行Client,w18上运行Server,运行正常
失败场景
- 在
q2上运行Server,w18上运行Client时,客户端Socket无法创建,超时后抛出错误:
java.net.ConnectException: Connection timed out (Connection timed out) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at java.net.Socket.<init>(Socket.java:434) at java.net.Socket.<init>(Socket.java:211) at Client.main(Client.java:21)
排查思路
单向连接失败的核心原因集中在防火墙/安全组限制、Server绑定IP错误或网络路由问题,可按以下步骤逐一验证:
验证Server监听地址
在q2启动Server后,执行端口监听检查命令:- Linux:
netstat -anp | grep 3112 - Windows:
netstat -ano | findstr 3112
确认监听地址为10.90.50.101:3112或0.0.0.0:3112(允许外部访问),如果是127.0.0.1:3112,则仅本机可连接,需修正file.cfg或Server绑定逻辑。
- Linux:
检查防火墙/安全组规则
- Linux:执行
iptables -L -n | grep 3112,确认是否允许w18(10.90.50.102)的入站连接到3112端口; - Windows:在Windows Defender防火墙高级设置中,确认存在允许3112端口入站的规则;
- 若为云主机,检查网络安全组是否开放
q2的3112端口给w18的IP。
- Linux:执行
网络连通性测试
在w18上执行:ping 10.90.50.101:确认两台主机网络可达;telnet 10.90.50.101 3112:若超时则端口不通,优先排查防火墙或监听问题;若能连接,再检查代码逻辑。
Server启动状态验证
确认q2上的Server启动时控制台输出Server Socket is created.,无绑定异常。若抛出IOException,需检查IP是否正确、端口是否被占用。
内容的提问来源于stack exchange,提问作者Shashank Gb
相关产品推荐
相关产品推荐

