同一局域网下Java Socket客户端无法连接服务器:Ping通但Telnet失败的问题求助
同一局域网下Java Socket客户端无法连接服务器:Ping通但Telnet失败的问题求助
我最近在做一个Java项目,功能是客户端通过Socket给服务器传文件,服务器处理后返回结果。在我自己电脑上运行完全没问题,但把客户端放到朋友电脑上(同一局域网,已经把Client.java里的IP从localhost改成服务器的IP),就出现连接超时的情况。
客户端能ping通服务器,但用命令telnet <server_ip> <port>测试时连接失败。我们试过各种办法:关闭防火墙、给对应端口添加 inbound/outbound 规则、关闭杀毒软件,也确认了服务器确实在监听指定端口,但客户端这边还是连不上。有没有大佬能给点建议或者帮忙排查下问题?
服务器代码(server.java)
package server; import common.ServerInterface; import common.Task; import common.Result; import java.rmi.server.UnicastRemoteObject; import java.rmi.RemoteException; import java.rmi.Naming; import java.net.ServerSocket; import java.net.Socket; import java.io.*; import java.util.Stack; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class Server extends UnicastRemoteObject implements ServerInterface { private static final int PORT = 12345; // Listening Port protected Server() throws RemoteException { super(); } private Stack<Task> taskStack = new Stack<>(); // Tasks private Map<String, Result> results = new HashMap<>(); // stores result as task ID @Override public synchronized Task getTask() throws RemoteException { if (!taskStack.isEmpty()) { return taskStack.pop(); // Retuns task if available } return null; // no task available } @Override public synchronized void returnResult(Result result, String taskId) throws RemoteException { // stores the result results.put(taskId, result); System.out.println("Results were received from Worker through RMI for the task " + taskId + ": " + result); } public void startSocketServer() { new Thread(() -> { try (ServerSocket serverSocket = new ServerSocket(PORT)) { System.out.println("Server is waiting for a connection on port " + PORT); while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected : " + clientSocket.getInetAddress()); // Gérer la connexion client new Thread(() -> handleClient(clientSocket)).start(); } } catch (IOException e) { e.printStackTrace(); } }).start(); } private void handleClient(Socket clientSocket) { try (InputStream is = clientSocket.getInputStream(); DataInputStream dis = new DataInputStream(is); OutputStream os = clientSocket.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) { int fileCount = dis.readInt(); // read the number String taskId = UUID.randomUUID().toString(); // generate ID for task Task task = new Task(taskId); // create a new task int textFileCount = 0; for (int i = 0; i < fileCount; i++) { String fileName = dis.readUTF(); // read file name long fileSize = dis.readLong(); // read file size byte[] fileContent = new byte[(int) fileSize]; dis.readFully(fileContent); // read all files on memory if (fileName.endsWith(".txt")) { String fileContentStr = new String(fileContent); // convert matrices to string if (textFileCount == 0) { task.setDataFile1Content(fileContentStr); } else if (textFileCount == 1) { task.setDataFile2Content(fileContentStr); } textFileCount++; } else if (fileName.endsWith(".jar")) { task.setOperationFileContent(fileContent); // stores in binary } } taskStack.push(task); // Add task System.out.println("Tak added : " + task); // wait for result while (!results.containsKey(taskId)) { Thread.sleep(1000); } // send result back to the client Result result = results.get(taskId); dos.writeUTF(result.getValue()); System.out.println("Result sent to client : " + result); clientSocket.close(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { try { Server server = new Server(); java.rmi.registry.LocateRegistry.createRegistry(1099); Naming.rebind("Server", server); System.out.println("Server RMI is ready"); // run server server.startSocketServer(); } catch (Exception e) { e.printStackTrace(); } } }
客户端代码(Client.java)
import java.io.*; import java.net.Socket; public class Client { public void sendTask(String serverAddress, String[] filePaths) { try (Socket socket = new Socket(serverAddress, 12345); OutputStream os = socket.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); InputStream is = socket.getInputStream(); DataInputStream dis = new DataInputStream(is)) { // Send number of files dos.writeInt(filePaths.length); for (String filePath : filePaths) { File file = new File(filePath); if (!file.exists()) { System.err.println("Error : File " + filePath + " does not exist !"); return; } // send file name dos.writeUTF(file.getName()); // send file size dos.writeLong(file.length()); // send file content try (FileInputStream fis = new FileInputStream(file)) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { dos.write(buffer, 0, bytesRead); } } } System.out.println("Task was sent to server"); // receive final result String result = dis.readUTF(); System.out.println("Results were received from the server : " + result); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { Client client = new Client(); String[] files = { "resources/data/A.txt", "resources/data/B.txt", "resources/operations/operation.jar" }; client.sendTask("192.168.43.19", files); } }
补充说明
我在自己电脑上运行服务器,朋友电脑运行客户端,预期是文件内容能成功发送,但实际连接超时。已经尝试关闭防火墙、添加端口规则,还是没解决。代码在localhost环境下完全正常,所以应该不是代码逻辑的问题。
可能的排查方向
- 确认服务器绑定的IP地址:你的
ServerSocket创建时用的是new ServerSocket(PORT),理论上会绑定到0.0.0.0(所有可用网卡),但可以在服务器上用netstat -ano | findstr 12345(Windows)或netstat -tulpn | grep 12345(Linux)检查,确认监听的是0.0.0.0:12345而不是127.0.0.1:12345——如果是后者,局域网其他机器肯定连不上。 - 检查局域网IP是否正确:确认客户端用的服务器IP是服务器在局域网内的真实IPv4地址(比如服务器运行
ipconfig/ifconfig得到的地址),有时候可能会误填成公网IP或者其他网卡的IP。 - 路由器/交换机的限制:如果你们是通过路由器连接的同一局域网,有些路由器可能开启了AP隔离功能,会阻止局域网内设备之间的直接通信。可以登录路由器后台,看看有没有“AP隔离”“客户端隔离”这类选项,关掉试试。
- 端口占用问题:虽然你确认服务器在运行端口,但可以再检查下服务器上有没有其他进程占用了12345端口,用上面的
netstat命令就能看到。 - 测试简化版连接:写一个最基础的Socket服务器和客户端,比如服务器只监听端口并打印连接信息,客户端只尝试连接,排除业务代码的干扰。如果这个简化版也连不上,那肯定是网络配置问题;如果能连上,再回头看你的业务代码有没有隐藏的问题。
- 检查Windows Defender高级设置:有时候只关闭防火墙主开关没用,需要在“高级安全Windows Defender防火墙”里,确认针对12345端口的入站规则是允许所有远程IP,而不是只允许localhost。
备注:内容来源于stack exchange,提问作者ms maam




