-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathServer.java
More file actions
95 lines (78 loc) · 3.56 KB
/
Server.java
File metadata and controls
95 lines (78 loc) · 3.56 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
import java.net.*;
import java.io.*;
import java.util.*;
public class Server {
public static final int CHAT_PORT = 7777;
public static final int FILE_PORT = 8888;
public static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
public static Map<String, ClientHandler> clients =
Collections.synchronizedMap(new HashMap<>());
private static final Queue<Socket> waiting = new LinkedList<>();
public static void main(String[] args) {
System.out.println("Chat server started...");
new Thread(Server::startChatServer).start();
new Thread(Server::startFileRelayServer).start();
}
private static void startChatServer() {
try (ServerSocket server = new ServerSocket(CHAT_PORT)) {
while (true) {
Socket socket = server.accept();
new Thread(new ClientHandler(socket)).start(); //handles a new client now
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void startFileRelayServer() {
try (ServerSocket fileServer = new ServerSocket(FILE_PORT)) { //try-with-resources;;; Java will automatically close the server socket once program ends or any exception occurs
while (true) {
Socket socket = fileServer.accept();
synchronized (waiting) {
waiting.add(socket);
if (waiting.size() >= 2) {
Socket s1 = waiting.poll();
Socket s2 = waiting.poll();
relay(s1, s2);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*
A problem of file begin received from other computer but of always size 0 striked.
Server relay was one-directional means if If receiver connects first then no data flows
Assumption it made
“The first socket is always the sender
The second socket is always the receiver”
Why this failed across PCs
Network timing is unpredictable
Sometimes receiver connects first
Server then listens to the wrong direction
Result: 0-byte files
*/
private static void relay(Socket a, Socket b) {
new Thread(() -> pipe(a, b)).start();
new Thread(() -> pipe(b, a)).start();
}
private static void pipe(Socket from, Socket to) {
try ( //try-with-resources ensures resouces are closed automatically after they are used
InputStream in = from.getInputStream();
OutputStream out = to.getOutputStream()
) {
byte[] buffer = new byte[4096]; //this is a temporary byte container(4KB), used to move data in chunks, not one byte at a time
int read; //stores how many bytes were actually read from the sender, read can be less be less than 4096 especially near the EOF
while((read = in.read(buffer)) != -1){ //read() reads bytes from sender's socket and stores them in buffer, RETURNS "no. of bytes read" OR "-1 when sender closes stream (EOF)"
out.write(buffer, 0, read); //writes exactly the bytes just read from index 0 upto 'read' bytes (we must not write the whole buffer blindly)
}
} catch (Exception ignored) {}
}
public static void broadcast(String msg) {
synchronized (clients) { //acquire lock on clients
for (ClientHandler ch : clients.values()) {
ch.send(msg);
}
}
}
}