Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove accidental backticks from .gitignore.

Line 1 and Line 7 appear to contain literal `````` entries, which look unintended and add noise to ignore rules.

Suggested cleanup
-``
 # Compiled Java classes
 *.class

 # Build directory
 bin/
-``

Also applies to: 7-7

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore at line 1, Remove the accidental backtick entries from the
.gitignore file: locate the lines containing only backtick characters (the
literal "```" entries at the top and at line 7) and delete those lines so they
no longer appear as ignore rules; keep all other ignore patterns unchanged.

# Compiled Java classes
*.class

# Build directory
bin/
```
Binary file modified bin/TCP/TCPClient.class
Binary file not shown.
Binary file modified bin/TCP/TCPServer.class
Binary file not shown.
Binary file modified bin/UDP/UDPClient.class
Binary file not shown.
Binary file modified bin/UDP/UDPServer.class
Binary file not shown.
163 changes: 163 additions & 0 deletions src/TCP/TCPClientGUI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package TCP;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class TCPClientGUI extends JFrame {
private JTextField hostField;
private JSpinner portSpinner;
private JTextArea messageArea;
private JTextField inputField;
private JButton connectButton;
private JButton sendButton;
private Socket socket;
private PrintWriter out;
private BufferedReader in;
private boolean connected = false;

public TCPClientGUI() {
super("TCP Client GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 500);
setLocationRelativeTo(null);

// Create components
JPanel topPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.anchor = GridBagConstraints.WEST;

topPanel.add(new JLabel("Host:"), gbc);
gbc.gridx = 1;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
hostField = new JTextField("localhost", 15);
topPanel.add(hostField, gbc);

gbc.gridx = 2;
gbc.weightx = 0;
gbc.fill = GridBagConstraints.NONE;
topPanel.add(new JLabel("Port:"), gbc);
gbc.gridx = 3;
portSpinner = new JSpinner(new SpinnerNumberModel(5000, 1, 65535, 1));
topPanel.add(portSpinner, gbc);

gbc.gridx = 4;
connectButton = new JButton("Connect");
connectButton.addActionListener(e -> toggleConnection());
topPanel.add(connectButton, gbc);

// Message display area
messageArea = new JTextArea();
messageArea.setEditable(false);
messageArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
JScrollPane scrollPane = new JScrollPane(messageArea);
scrollPane.setPreferredSize(new Dimension(0, 300));

// Input panel
JPanel inputPanel = new JPanel(new BorderLayout());
inputField = new JTextField();
inputField.setEnabled(false);
inputField.addActionListener(e -> sendMessage());
sendButton = new JButton("Send");
sendButton.setEnabled(false);
sendButton.addActionListener(e -> sendMessage());

inputPanel.add(inputField, BorderLayout.CENTER);
inputPanel.add(sendButton, BorderLayout.EAST);

// Layout
setLayout(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
add(inputPanel, BorderLayout.SOUTH);

setVisible(true);
}

private void toggleConnection() {
if (!connected) {
connect();
} else {
disconnect();
}
}

private void connect() {
String host = hostField.getText().trim();
int port = (Integer) portSpinner.getValue();

try {
socket = new Socket(host, port);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "TCPClientGUI.java" -type f

Repository: Bendz07/TCP_UDP-Java

Length of output: 91


🏁 Script executed:

cat -n "src/TCP/TCPClientGUI.java" | head -150

Repository: Bendz07/TCP_UDP-Java

Length of output: 5963


🏁 Script executed:

tail -50 "src/TCP/TCPClientGUI.java"

Repository: Bendz07/TCP_UDP-Java

Length of output: 1544


Move socket connection to a background thread with a finite timeout to prevent GUI freezing.

Line 94 executes new Socket(host, port) directly on the Swing event thread (called from the Connect button's action listener). This blocking call can freeze the GUI for the OS TCP timeout duration when the host is unreachable or slow to respond.

Refactor the connection logic into a SwingWorker that:

  1. Creates and connects the socket with a finite timeout (e.g., 5 seconds)
  2. Updates UI components back on the EDT upon success or failure

For example, use Socket.connect(new InetSocketAddress(host, port), 5000) instead of the parameterless constructor to enforce a timeout.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/TCP/TCPClientGUI.java` at line 94, The direct call socket = new
Socket(host, port) in the Connect button's action listener blocks the EDT;
refactor the connection into a SwingWorker (or background Thread) that performs
socket connection using socket.connect(new InetSocketAddress(host, port), 5000)
to enforce a 5s timeout, then publish results back to the EDT to update UI
components (enable/disable buttons, show error dialogs, update status) in
done()/publish/process; locate the connection code around the Connect button
action listener and replace it with a SwingWorker that creates the Socket with a
timeout and handles success/failure on the EDT.

out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

connected = true;
connectButton.setText("Disconnect");
inputField.setEnabled(true);
sendButton.setEnabled(true);
hostField.setEnabled(false);
portSpinner.setEnabled(false);
messageArea.append("Connected to server at " + host + ":" + port + "\n");

// Start reader thread
new Thread(this::readFromServer).start();

} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Failed to connect: " + e.getMessage(),
"Connection Error", JOptionPane.ERROR_MESSAGE);
disconnect();
}
}

private void disconnect() {
connected = false;
connectButton.setText("Connect");
inputField.setEnabled(false);
sendButton.setEnabled(false);
hostField.setEnabled(true);
portSpinner.setEnabled(true);
messageArea.append("Disconnected from server\n");

try {
if (socket != null && !socket.isClosed()) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

private void readFromServer() {
String line;
try {
while (connected && (line = in.readLine()) != null) {
String finalLine = line;
SwingUtilities.invokeLater(() -> messageArea.append("Server: " + finalLine + "\n"));
}
} catch (IOException e) {
if (connected) {
SwingUtilities.invokeLater(() -> {
messageArea.append("Connection lost: " + e.getMessage() + "\n");
disconnect();
});
Comment on lines +134 to +146
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "TCPClientGUI.java" -type f

Repository: Bendz07/TCP_UDP-Java

Length of output: 91


🏁 Script executed:

git ls-files | grep -i tcp

Repository: Bendz07/TCP_UDP-Java

Length of output: 209


🏁 Script executed:

cat -n ./src/TCP/TCPClientGUI.java

Repository: Bendz07/TCP_UDP-Java

Length of output: 6441


Reset only the connection owned by this reader.

readFromServer() uses shared in, socket, and connected fields. A stale reader from an old socket can catch an exception after reconnection and call disconnect(), closing the new socket instead. Additionally, a clean server EOF exits the read loop silently without notifying the UI or disconnecting.

Pass socket and reader as method parameters to give each thread its own snapshot, and check socket identity before performing disconnect operations:

Proposed fix
-            new Thread(this::readFromServer).start();
+            Socket clientSocket = socket;
+            BufferedReader reader = in;
+            new Thread(() -> readFromServer(clientSocket, reader), "tcp-client-reader").start();
-    private void readFromServer() {
+    private void readFromServer(Socket clientSocket, BufferedReader reader) {
         String line;
+        boolean shouldDisconnect = false;
         try {
-            while (connected && (line = in.readLine()) != null) {
+            while (connected && socket == clientSocket && (line = reader.readLine()) != null) {
                 String finalLine = line;
                 SwingUtilities.invokeLater(() -> messageArea.append("Server: " + finalLine + "\n"));
             }
+            shouldDisconnect = connected && socket == clientSocket;
         } catch (IOException e) {
-            if (connected) {
+            shouldDisconnect = connected && socket == clientSocket;
+            if (shouldDisconnect) {
                 SwingUtilities.invokeLater(() -> {
                     messageArea.append("Connection lost: " + e.getMessage() + "\n");
                     disconnect();
                 });
             }
+            return;
+        }
+
+        if (shouldDisconnect) {
+            SwingUtilities.invokeLater(() -> {
+                messageArea.append("Connection closed by server\n");
+                disconnect();
+            });
         }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/TCP/TCPClientGUI.java` around lines 134 - 146, Update readFromServer to
accept the specific Socket and BufferedReader used by that reader thread (e.g.,
change readFromServer() to readFromServer(Socket readerSocket, BufferedReader
reader)) and use those local parameters instead of the shared fields (in,
socket, connected) so each thread has its own snapshot; inside the loop detect
EOF (reader.readLine() == null) and on EOF post a UI message via
SwingUtilities.invokeLater to append "Connection closed by server" and call
disconnect only if readerSocket == this.socket (compare socket identity) to
avoid closing a newer connection, and likewise in the IOException handler check
that the caught exception belongs to the same readerSocket before invoking
disconnect() and updating messageArea.

}
}
}

private void sendMessage() {
String message = inputField.getText().trim();
if (!message.isEmpty() && connected) {
out.println(message);
messageArea.append("You: " + message + "\n");
Comment on lines +153 to +155
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd TCPClientGUI.java

Repository: Bendz07/TCP_UDP-Java

Length of output: 89


🏁 Script executed:

cat -n src/TCP/TCPClientGUI.java | sed -n '150,160p'

Repository: Bendz07/TCP_UDP-Java

Length of output: 465


🏁 Script executed:

cat -n src/TCP/TCPClientGUI.java | grep -n "PrintWriter\|out\s*=" | head -20

Repository: Bendz07/TCP_UDP-Java

Length of output: 179


🏁 Script executed:

cat -n src/TCP/TCPClientGUI.java | sed -n '1,30p'

Repository: Bendz07/TCP_UDP-Java

Length of output: 1140


🏁 Script executed:

cat -n src/TCP/TCPClientGUI.java | sed -n '85,105p'

Repository: Bendz07/TCP_UDP-Java

Length of output: 930


🏁 Script executed:

cat -n src/TCP/TCPClientGUI.java | sed -n '110,140p'

Repository: Bendz07/TCP_UDP-Java

Length of output: 1282


Check write failures before showing the message as sent.

PrintWriter suppresses I/O exceptions, so out.println(message) at line 154 can fail silently while line 155 still logs "You: …". Use out.checkError() to detect failures and notify the user instead of silently dropping the message.

Proposed fix
         String message = inputField.getText().trim();
         if (!message.isEmpty() && connected) {
-            out.println(message);
-            messageArea.append("You: " + message + "\n");
-            inputField.setText("");
+            try {
+                out.println(message);
+                if (out.checkError()) {
+                    throw new IOException("Failed to write to server");
+                }
+                messageArea.append("You: " + message + "\n");
+                inputField.setText("");
+            } catch (IOException e) {
+                JOptionPane.showMessageDialog(this, "Failed to send: " + e.getMessage(),
+                        "Send Error", JOptionPane.ERROR_MESSAGE);
+                disconnect();
+            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/TCP/TCPClientGUI.java` around lines 153 - 155, The message is appended as
"You: ..." before ensuring the PrintWriter actually wrote it; update the send
path in the block that uses out.println(message) (and the connected flag) to
flush and then call out.checkError() to detect write failures, and only append
"You: ..." to messageArea (or otherwise notify success) when checkError()
reports no error; if checkError() indicates failure, display an error
notification to the user instead of logging the message as sent. Ensure you
modify the code around out.println(message), out.flush()/autoFlush behavior, and
messageArea append so failures are handled correctly.

inputField.setText("");
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(TCPClientGUI::new);
}
}
133 changes: 133 additions & 0 deletions src/TCP/TCPServerGUI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package TCP;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.concurrent.atomic.AtomicBoolean;

public class TCPServerGUI extends JFrame {
private JSpinner portSpinner;
private JButton startButton;
private JTextArea logArea;
private ServerSocket serverSocket;
private AtomicBoolean running = new AtomicBoolean(false);

public TCPServerGUI() {
super("TCP Server GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 500);
setLocationRelativeTo(null);

// Top panel with port and start button
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
topPanel.add(new JLabel("Port:"));
portSpinner = new JSpinner(new SpinnerNumberModel(5000, 1, 65535, 1));
topPanel.add(portSpinner);
startButton = new JButton("Start Server");
startButton.addActionListener(e -> toggleServer());
topPanel.add(startButton);

// Log area
logArea = new JTextArea();
logArea.setEditable(false);
logArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
JScrollPane scrollPane = new JScrollPane(logArea);

// Layout
setLayout(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);

setVisible(true);
}

private void toggleServer() {
if (!running.get()) {
startServer();
} else {
stopServer();
}
}

private void startServer() {
int port = (Integer) portSpinner.getValue();
try {
serverSocket = new ServerSocket(port);
running.set(true);
startButton.setText("Stop Server");
portSpinner.setEnabled(false);
logArea.append("TCP Server started on port " + port + "\n");

// Accept clients in a separate thread
new Thread(this::acceptClients).start();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "TCPServerGUI.java" -type f

Repository: Bendz07/TCP_UDP-Java

Length of output: 91


🏁 Script executed:

cat -n src/TCP/TCPServerGUI.java

Repository: Bendz07/TCP_UDP-Java

Length of output: 5348


Bind accept loop to specific ServerSocket instance and update log area safely from EDT.

Two issues in acceptClients():

  1. Race condition: Line 63 starts a thread reading the mutable serverSocket field. A rapid stop/start sequence can cause the old accept thread to resume after running is set true again and inadvertently accept clients on the new socket instance. The thread should be bound to the specific ServerSocket instance created when it starts.

  2. Unsafe Swing mutations: Lines 76 and 83 call logArea.append() directly from the background accept thread. Swing components must be updated on the Event Dispatch Thread (EDT). Compare with the correct usage in handleClient() (lines 96-97, 104-105) which uses SwingUtilities.invokeLater().

Proposed fix
-            new Thread(this::acceptClients).start();
+            ServerSocket boundServerSocket = serverSocket;
+            new Thread(() -> acceptClients(boundServerSocket), "tcp-server-accept").start();
-    private void acceptClients() {
-        while (running.get()) {
+    private void acceptClients(ServerSocket boundServerSocket) {
+        while (running.get() && !boundServerSocket.isClosed()) {
             try {
-                Socket clientSocket = serverSocket.accept();
-                logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n");
+                Socket clientSocket = boundServerSocket.accept();
+                SwingUtilities.invokeLater(() -> 
+                    logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n"));
 
                 // Handle each client in a separate thread
                 new Thread(() -> handleClient(clientSocket)).start();
 
             } catch (IOException e) {
                 if (running.get()) {
-                    logArea.append("Error accepting client: " + e.getMessage() + "\n");
+                    SwingUtilities.invokeLater(() -> 
+                        logArea.append("Error accepting client: " + e.getMessage() + "\n"));
                 }
             }
         }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
new Thread(this::acceptClients).start();
ServerSocket boundServerSocket = serverSocket;
new Thread(() -> acceptClients(boundServerSocket), "tcp-server-accept").start();
Suggested change
new Thread(this::acceptClients).start();
private void acceptClients(ServerSocket boundServerSocket) {
while (running.get() && !boundServerSocket.isClosed()) {
try {
Socket clientSocket = boundServerSocket.accept();
SwingUtilities.invokeLater(() ->
logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n"));
// Handle each client in a separate thread
new Thread(() -> handleClient(clientSocket)).start();
} catch (IOException e) {
if (running.get()) {
SwingUtilities.invokeLater(() ->
logArea.append("Error accepting client: " + e.getMessage() + "\n"));
}
}
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/TCP/TCPServerGUI.java` at line 63, The accept thread currently reads the
mutable field serverSocket and calls logArea.append() from the background
thread; fix acceptClients() so it captures the ServerSocket instance into a
local final variable when the thread starts (e.g., final ServerSocket
localSocket = this.serverSocket) and use that localSocket for accept() to avoid
accepting on a replaced socket, and change all direct calls to
logArea.append(...) in acceptClients() to wrap their UI updates in
SwingUtilities.invokeLater(() -> logArea.append(...)) to ensure EDT-safe updates
(mirror the pattern used in handleClient()).


} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Failed to start server: " + e.getMessage(),
"Server Error", JOptionPane.ERROR_MESSAGE);
stopServer();
}
}

private void acceptClients() {
while (running.get()) {
try {
Socket clientSocket = serverSocket.accept();
logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n");

// Handle each client in a separate thread
new Thread(() -> handleClient(clientSocket)).start();

} catch (IOException e) {
if (running.get()) {
logArea.append("Error accepting client: " + e.getMessage() + "\n");
Comment on lines +76 to +83
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "TCPServerGUI.java" -type f

Repository: Bendz07/TCP_UDP-Java

Length of output: 91


🏁 Script executed:

cat -n ./src/TCP/TCPServerGUI.java | head -100

Repository: Bendz07/TCP_UDP-Java

Length of output: 4225


🏁 Script executed:

rg "logArea\.append" ./src/TCP/TCPServerGUI.java -n

Repository: Bendz07/TCP_UDP-Java

Length of output: 598


🏁 Script executed:

cat -n ./src/TCP/TCPServerGUI.java | tail -30

Repository: Bendz07/TCP_UDP-Java

Length of output: 1116


Route accept-loop log updates through the EDT.

Lines 76 and 83 update logArea from the acceptClients() method, which runs on a background thread spawned at line 63. Swing components must only be modified on the event dispatch thread. The codebase already demonstrates the correct pattern in the handleClient() method (lines 96–97, 104–105) using SwingUtilities.invokeLater().

Proposed fix
-                logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n");
+                SwingUtilities.invokeLater(() ->
+                        logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n"));
...
                 if (running.get()) {
-                    logArea.append("Error accepting client: " + e.getMessage() + "\n");
+                    SwingUtilities.invokeLater(() ->
+                            logArea.append("Error accepting client: " + e.getMessage() + "\n"));
                 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n");
// Handle each client in a separate thread
new Thread(() -> handleClient(clientSocket)).start();
} catch (IOException e) {
if (running.get()) {
logArea.append("Error accepting client: " + e.getMessage() + "\n");
SwingUtilities.invokeLater(() ->
logArea.append("Client connected: " + clientSocket.getInetAddress() + "\n"));
// Handle each client in a separate thread
new Thread(() -> handleClient(clientSocket)).start();
} catch (IOException e) {
if (running.get()) {
SwingUtilities.invokeLater(() ->
logArea.append("Error accepting client: " + e.getMessage() + "\n"));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/TCP/TCPServerGUI.java` around lines 76 - 83, The accept loop is updating
the Swing logArea from a background thread in acceptClients(); wrap the
logArea.append calls (e.g., the "Client connected: " message and the error
message in the catch) in SwingUtilities.invokeLater so they run on the EDT,
mirroring the pattern used in handleClient() where log updates are performed
inside SwingUtilities.invokeLater; update the logArea.append(...) invocations
that reference clientSocket and e.getMessage() to be executed inside a Runnable
passed to SwingUtilities.invokeLater and keep the surrounding acceptClients(),
running, and clientSocket logic unchanged.

}
}
}
}

private void handleClient(Socket clientSocket) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {

String message;
while ((message = in.readLine()) != null) {
String finalMessage = message;
SwingUtilities.invokeLater(() ->
logArea.append("Received from " + clientSocket.getInetAddress() + ": " + finalMessage + "\n"));

String response = "Echo: " + message;
out.println(response);
}

} catch (IOException e) {
SwingUtilities.invokeLater(() ->
logArea.append("Client disconnected: " + clientSocket.getInetAddress() + "\n"));
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

private void stopServer() {
running.set(false);
startButton.setText("Start Server");
portSpinner.setEnabled(true);
logArea.append("TCP Server stopped\n");

try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
Comment on lines +115 to +123
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "TCPServerGUI.java" | head -20

Repository: Bendz07/TCP_UDP-Java

Length of output: 91


🏁 Script executed:

cat -n ./src/TCP/TCPServerGUI.java

Repository: Bendz07/TCP_UDP-Java

Length of output: 5348


Close all active client sockets when stopping the server.

When stopServer() closes only the listening socket, handler threads remain blocked in readLine() waiting for client input. These threads continue executing and can process messages even after the UI indicates the server has stopped. To properly shut down all connections, track client sockets in a concurrent collection, add them when accepted, and close them all during shutdown.

The proposed fix correctly addresses this by:

  • Maintaining a thread-safe set of active client sockets
  • Adding sockets to the set in acceptClients()
  • Removing sockets in the finally block of handleClient()
  • Closing all remaining sockets in stopServer() to interrupt blocked readLine() calls
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/TCP/TCPServerGUI.java` around lines 115 - 123, stopServer() currently
only closes the listening ServerSocket, leaving handler threads blocked on
readLine(); fix by adding a thread-safe collection (e.g.,
ConcurrentHashMap.newKeySet() or ConcurrentSkipListSet) named activeClients to
track client Socket objects, add each accepted socket in acceptClients() when
you call serverSocket.accept(), remove the socket in the finally block of
handleClient(), and iterate over activeClients in stopServer() to close each
Socket (and clear the set) so blocked reader threads are interrupted and all
client connections are terminated.

}
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(TCPServerGUI::new);
}
}
Loading