As an engineer, I have always been fascinated by the vast and diverse world of engineering. One area that has particularly captivated my attention is distributed systems, and I have been eager to learn more about them. Recently, I have been hearing a lot about chatGPT, and I was intrigued by the potential of this approach as a tool for learning about distributed systems.
In order to explore the potential of this approach, I decided to conduct an experiment using chatGPT to prototype a simple distributed chat system. I was curious to see if chatGPT could provide the guidance and assistance needed to prototype such a system, and whether it could be an effective tool for early career engineers like myself.
My goal for this experiment was to create a straightforward single-server, dual-client chat system. I wanted to minimize modifications to the provided code, and see if I could use it as is while still gaining an understanding of how it works, like a plug and play solution.
Initially, I requested that chatGPT provide me with a diagram of the architecture for a single-server distributed chat system.
- Can you draw me a simple one server distributed chat system architecture diagram?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| +------------+
| |
| Client 1 |
| |
+------+-----+
|
| +------------+
+------>+ |
| Server 1 |
| |
+------------+
+------+--------+
| |
| Client 2 |
| |
+------------+
|
From the drawing, I can see what chatGPT was trying to convey. The server would have had the ability to read and send messages, relaying them to the appropriate destinations. Although this diagram wasn’t entirely correct, I decided to use the approach that I thought chatGPT was suggesting in order to continue.
My next step was to create the server.
- Can you write me a server in java that listens and relays in a local network?
This is the server chatGPT provided me
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
| import java.io.*;
import java.net.*;
import java.util.*;
public class MessageRelayServer {
public static void main(String[] args) throws IOException {
// Create a new server socket on localhost port 1234
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("MessageRelayServer started on localhost:1234");
// Create a list to store connected clients
List<Socket> clients = new ArrayList<>();
// Continuously accept new client connections
while (true) {
// Accept a new client connection
Socket client = serverSocket.accept();
// Add the new client to the list of connected clients
clients.add(client);
// Print a message to the console
System.out.println("New client connected: + client.getRemoteSocketAddress()");
// Create a new thread to handle communication with the client
new Thread(() -> {
try {
// Create input and output streams for the client
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
while (true) {
// Read a message from the client
String message = in.readLine();
// Print the message to the console
System.out.println("Received message from " + client.getRemoteSocketAddress() + ":" + message);
// Send the message to all other clients, excluding the client that sent the
// message
for (Socket otherClient : clients) {
if (otherClient != client) {
out.println(message);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
|
Now that the server is up and running time to create the clients…
- Now, can you write a client that sends and listens to this server?
The client implementation provided by chatGPT
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
| import java.io.*;
import java.net.*;
import java.util.logging.*;
public class MessageRelayClient {
private static final Logger logger = Logger.getLogger(MessageRelayClient.class.getName());
public static void main(String[] args) throws IOException {
// Create a socket to connect to the server
Socket socket = new Socket("localhost", 1234);
// Create input and output streams to read from and write to the server
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// Listen for messages from the server in a separate thread
Thread listener = new Thread(() -> {
try {
String response;
while ((response = in.readLine()) != null) {
logger.info("Received message from server:" + response);
System.out.println(response);
}
} catch (IOException e) {
logger.severe("Error reading from server: + e.getMessage()");
}
});
listener.start();
// Read input from the CLI and write it to the server
BufferedReader cli = new BufferedReader(new InputStreamReader(System.in));
String input;
while ((input = cli.readLine()) != null) {
out.println(input);
logger.info("Sent message to server: " + input);
}
// Close the socket when done
socket.close();
}
}
|
Initially, there were several issues with my question. It was not specific enough, and chatGPT needed more information in order to provide an accurate response. For example, I didn’t mention that I wanted logging or that the client should be connected to port 1234. Additionally, the server code had some errors, such as comparing Socket
objects instead of their RemoteSocketAddress
strings, and using the wrong PrintWriter
to send messages. These issues were addressed in the revised code provided by chatGPT.
The final code implementation provided by chatGPT was successful in addressing the issues with the initial code and providing a functional messaging system.
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
| import java.io.*;
import java.net.*;
import java.util.*;
public class MessageRelayServerFinal {
public static void main(String[] args) throws IOException {
// Create a new server socket on localhost port 1234
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("MessageRelayServer started on localhost:1234");
// Create a list to store connected clients
List<Socket> clients = new ArrayList<>();
// Continuously accept new client connections
while (true) {
// Accept a new client connection
Socket client = serverSocket.accept();
// Add the new client to the list of connected clients
clients.add(client);
// Print a message to the console
System.out.println("New client connected: " + client.getRemoteSocketAddress());
// Create a new thread to handle communication with the client
new Thread(() -> {
try {
// Create input and output streams for the client
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
// PrintWriter out = new PrintWriter(client.getOutputStream(), true); -> This was sending it to itself
// Continuously read messages from the client
while (true) {
// Read a message from the client
String message = in.readLine();
// Print the message to the console
System.out.println("Received message from " + client.getRemoteSocketAddress() + ": " + message);
// Send the message to all other clients, excluding the client that sent the message
for (Socket otherClient : clients) {
if (!otherClient.getRemoteSocketAddress().equals(client.getRemoteSocketAddress())) {
//Added: -> This now allow to write to other clients
PrintWriter otherClientOut = new PrintWriter(otherClient.getOutputStream(), true);
otherClientOut.println(message);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
|
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
| import java.io.*;
import java.net.*;
import java.util.logging.*;
public class MessageRelayClientFinal {
private static final Logger logger = Logger.getLogger(MessageRelayClient.class.getName());
public static void main(String[] args) throws IOException {
// Create a socket to connect to the server
Socket socket = new Socket("localhost", 1234);
// Create input and output streams to read from and write to the server
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// Listen for messages from the server in a separate thread
Thread listener = new Thread(() -> {
try {
String response;
while ((response = in.readLine()) != null) {
logger.info("Received message from server: " + response);
System.out.println(response);
}
} catch (IOException e) {
logger.severe("Error reading from server: " + e.getMessage());
}
});
listener.start();
// Read input from the CLI and write it to the server
BufferedReader cli = new BufferedReader(new InputStreamReader(System.in));
String input;
while ((input = cli.readLine()) != null) {
out.println(input);
logger.info("Sent message to server: " + input);
}
// Close the socket when done
socket.close();
}
}
|
Local test
It took me around 3 hours to get this “built”. It was a fun experiment, and I can see the potential for this technology to help many people understand complex concepts quickly. If I were to write this code from scratch, it would have easily taken me half a day or more. However, even though it would have taken longer, I believe I would have learned more in the process. Despite this, being able to prototype this code and see it work has given me a confidence boost and shown me what to expect in the world of distributed systems.
Although there is much more complexity in distributed systems, with the addition of components such as load balancers, data stores, and message brokers, I can say that using chatGPT has really helped me gain a glimpse into what the world of a distributed systems engineer may look like. I’m excited to see the future possibilities that this technology brings forward.
Code
Medium Article