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);
}
}
i我尝试在我的PC上运行服务器,然后在另一台PC上运行客户端。我希望将文件内容发送,但是连接时间已计时。我尝试禁用防火墙并添加规则以允许该端口的流量,但仍未解决。我确定我的代码有效,因为它使用localhost在我的PC上完美工作。
时间是您为Linux(Windows)配备Diag工具的时间:TCPDUMP(Wireshark),查看数据包飞行。在两端,如果其中一半通过。您还会查看它是TCP RST还是FIN或什么都没有。在这里,看来初始SYN没有得到任何响应,但是服务器可能已经看到了SYN并尝试响应,但数据包无法通过。
NETSTAT(资源监视器或TCPView),查看服务器端口的绑定地址。如果仅绑定到Localhost(IPv6中的127.0.0.1或:: 1),则它将不接受您的192.168上的SYN ....接口.
(另外,您可以通过删除分心的RMI内容来简化示例)。对于防火墙,您会惊讶地发现有多少个广泛规则可以捕捉您的流程。您不会说是Linux还是Windows,但是在Windows上,规则可能是重叠的可能性。我使用Malwarebytes WFC(Windows防火墙控件)来查看连接失败的日志以及哪个规则引起的。它还可以找到重复规则。使用详细的进程列表,请注意Java.exe或Javaw.exe可能正在运行的java.exe。我不熟悉Linux防火墙。
最终,开关或路由器也有可能干扰这一点。您可能最终需要访问那些(或这样做的人)。