如何配置Java Socket实现跨设备及跨网络通信?
Java网络编程:实现跨设备文件传输的修改方案
问题描述
我正在学习Java网络编程,实现文件和字符串传输,但目前仅能在localhost(本地主机)环境下运行。请问需要对现有代码做出哪些修改,才能实现与同一网络或其他网络中的设备通信?
我曾尝试将localhost替换为InetAddress.getLocalHost().getHostAddress()获取的IP地址,但未能成功,客户端持续报错:错误:java.net.ConnectException: 连接被拒绝
现有代码
Client.java
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.*; import java.nio.file.Files; import java.util.Arrays; public class Client { private int fileSize; private String FileName; public void getFileInformation (File newFile) { fileSize = (int) newFile.length(); FileName = newFile.getName(); } public static void main (String [] args) { try { Client newClient = new Client (); Socket newSocket = new Socket("localhost",3333); DataInputStream newDataInput = new DataInputStream(newSocket.getInputStream()); DataOutputStream newDataOutput = new DataOutputStream(newSocket.getOutputStream()); BufferedReader newReader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter path of file: "); File newFile = new File(newReader.readLine()); newClient.getFileInformation(newFile); newDataOutput.writeInt(newClient.fileSize); newDataOutput.writeUTF(newClient.FileName); byte [] fileData = Files.readAllBytes(newFile.toPath()); System.out.println(Arrays.toString(fileData)); newDataOutput.write(fileData); newSocket.close(); newDataInput.close(); newDataOutput.flush(); newDataOutput.close(); newReader.close(); } catch (IOException ex) { System.out.println("Error: " + ex); } } }
Server.java
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; public class Server { private int fileSize; private String FileName; public static void main (String [] args) { try { Server newServer = new Server(); ServerSocket newServerSocket = new ServerSocket(3333); Socket newSocket = newServerSocket.accept(); DataInputStream newDataInput = new DataInputStream(newSocket.getInputStream()); DataOutputStream newDataOutput = new DataOutputStream(newSocket.getOutputStream()); BufferedReader newReader = new BufferedReader(new InputStreamReader(System.in)); newServer.fileSize = newDataInput.readInt(); System.out.println(newServer.fileSize); newServer.FileName = newDataInput.readUTF(); System.out.println(newServer.FileName); byte [] fileData = new byte [newServer.fileSize]; newDataInput.readFully(fileData); FileOutputStream newOutputStream = new FileOutputStream(newServer.FileName); System.out.println(Arrays.toString(fileData)); newOutputStream.write(fileData); newOutputStream.close(); newSocket.close(); newDataInput.close(); newDataOutput.flush(); newDataOutput.close(); newReader.close(); } catch (IOException ex) { System.out.println("Error: " + ex); } } }
修改方案与问题排查
1. 服务器端:让ServerSocket监听所有网络接口
当前代码中ServerSocket默认只绑定localhost,无法接收其他设备的连接。修改为监听所有可用网络接口:
// 替换Server.java中的ServerSocket初始化代码 ServerSocket newServerSocket = new ServerSocket(3333, 50, InetAddress.getByName("0.0.0.0"));
0.0.0.0表示服务器会监听所有网卡的请求,包括局域网IP和公网IP- 可选添加
newServerSocket.setReuseAddress(true);,避免程序重启后端口被占用的问题
2. 客户端:指定服务器的实际IP地址
InetAddress.getLocalHost().getHostAddress()获取的是客户端自身的IP,必须替换为服务器设备的真实IP:
// 替换Client.java中的Socket初始化代码,把IP改成服务器的实际地址 Socket newSocket = new Socket("192.168.1.100", 3333);
- 同一网络下:使用服务器的局域网IP(可通过
ipconfig/ifconfig查看) - 跨网络下:使用服务器的公网IP,同时需要在路由器上配置端口映射(将3333端口转发到服务器的局域网IP)
3. 解决「连接被拒绝」的关键步骤
- 先启动服务器,再启动客户端:服务器必须处于监听状态才能接收连接
- 检查防火墙:服务器设备需开放3333端口,或临时关闭防火墙测试
- 网络连通性:同一网络下确保客户端能ping通服务器的IP
- 端口占用:确认3333端口没有被其他程序占用(可通过
netstat -ano | findstr 3333(Windows)或lsof -i :3333(Linux/macOS)查看)
4. 代码优化建议(可选)
- 调整资源关闭顺序:先关闭输出流,再关闭输入流,最后关闭Socket,避免资源泄漏
// 客户端正确的关闭顺序 newDataOutput.flush(); newDataOutput.close(); newDataInput.close(); newSocket.close(); newReader.close();
- 大文件处理:当前
Files.readAllBytes()会将整个文件加载到内存,大文件会导致内存溢出,建议改为分块读写:
// 客户端替换文件读取代码 try (InputStream in = Files.newInputStream(newFile.toPath())) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { newDataOutput.write(buffer, 0, bytesRead); } }
内容的提问来源于stack exchange,提问作者Network
相关产品推荐
相关产品推荐

