-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClientHandler.java
More file actions
127 lines (115 loc) · 5.29 KB
/
ClientHandler.java
File metadata and controls
127 lines (115 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import java.io.*;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ClientHandler implements Runnable {
private final Socket clientSocket;
private final SharedState sharedState;
private PrintWriter out;
private BufferedReader in;
private DataOutputStream dataOut;
public ClientHandler(Socket socket, SharedState sharedState) {
this.clientSocket = socket;
this.sharedState = sharedState;
}
@Override
public void run() {
String clientInfo = clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort();
// Critical Section: Modifying the shared state by adding a new client.
// Synchronized in SharedState to ensure thread safety.
sharedState.addClient(clientInfo);
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
dataOut = new DataOutputStream(clientSocket.getOutputStream());
String inputLine;
while ((inputLine = in.readLine()) != null) {
String[] tokens = inputLine.split(" ", 2);
String command = tokens[0].toUpperCase();
sharedState.logOperation("Received command '" + command + "' from " + clientInfo);
switch (command) {
case "LIST":
handleList();
break;
case "GET":
if (tokens.length > 1) {
handleGet(tokens[1]);
} else {
out.println("ERREUR : nom de fichier manquant.");
}
break;
case "QUIT":
return; // Exit the loop and close the connection.
default:
out.println("ERREUR : commande inconnue.");
}
}
} catch (IOException e) {
// This block catches I/O errors, such as an abrupt client disconnection.
System.err.println("Error handling client " + clientInfo + ": " + e.getMessage());
} finally {
// This 'finally' block ensures that cleanup happens whether the loop exits
// normally (QUIT) or due to an exception (abrupt disconnection).
try {
// Critical Section: Modifying shared state by removing a client.
// Synchronized in SharedState to ensure thread safety.
sharedState.removeClient(clientInfo);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void handleList() {
try (Stream<Path> stream = Files.list(Paths.get("shared"))) {
String fileList = stream
.filter(Files::isRegularFile)
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.joining("\n"));
// The response is sent as a multi-line string, terminated by a final empty line from the client's perspective.
out.println(fileList.isEmpty() ? "Aucun fichier disponible." : fileList);
out.println(); // Signal the end of the list
} catch (IOException e) {
out.println("ERREUR : impossible de récupérer la liste des fichiers.");
out.println(); // Signal the end of the error message
e.printStackTrace();
}
}
private void handleGet(String fileName) {
Path path = Paths.get("shared", fileName);
if (Files.exists(path) && Files.isRegularFile(path)) {
try {
long fileSize = Files.size(path);
// Protocol: First, send the file size as a long.
dataOut.writeLong(fileSize);
// Protocol: Second, send the file content as raw bytes.
try (InputStream fileIn = new FileInputStream(path.toFile())) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fileIn.read(buffer)) != -1) {
dataOut.write(buffer, 0, bytesRead);
}
dataOut.flush();
}
// Critical Section: Incrementing the download counter.
// Synchronized in SharedState to prevent race conditions.
sharedState.incrementDownloads();
sharedState.logOperation("File '" + fileName + "' downloaded by " + clientSocket.getInetAddress().getHostAddress());
} catch (IOException e) {
// The client might disconnect during transfer, leading to an IOException.
// We log this error instead of letting it crash the thread.
System.err.println("Error sending file " + fileName + ": " + e.getMessage());
}
} else {
try {
dataOut.writeLong(-1);
} catch (IOException e) {
System.err.println("Error signaling file not found: " + e.getMessage());
}
}
}
}