Java app can't be closed even "CLOSE ON EXIT", TCP Server - java

I just wanna make a Server application which gets Strings and put these into a JTextArea. There are two errors I get, even no errors are showed.
the window can't be closed although I used this statement:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
If the client connects to the Server, the whole window turns black. What could be the error? Here the code:
Client:
public Main() {
super("Main");
setIconImage(Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/images/ic.png")));
panelFields = new JPanel();
panelFields.setLayout(new BoxLayout(panelFields,BoxLayout.X_AXIS));
panelFields2 = new JPanel();
panelFields2.setLayout(new BoxLayout(panelFields2,BoxLayout.X_AXIS));
scrollPane = new JScrollPane();
panelFields.add(scrollPane);
getContentPane().add(panelFields);
getContentPane().add(panelFields2);
getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
setSize(326, 264);
setVisible(true);
messagesArea = new JTextArea();
scrollPane.setViewportView(messagesArea);
messagesArea.setColumns(30);
messagesArea.setRows(10);
messagesArea.setEditable(false);
startServer = new JButton("Start");
startServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
socketConnection();
startServer.setEnabled(false);
}
});
panelFields.add(startServer);
}
And the Server connection:
private void socketConnection() {
try {
serverSocket = new ServerSocket(9090);
System.out.println("Listening: " + serverSocket.getLocalPort());
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
System.out.println("ip: " + socket.getInetAddress());
System.out.println("message: " + dataInputStream.readUTF());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Maybe you could tell me, how I can fix those problems and also, how I can make, that the server doesn't close the socket although the client disconnects. I wanna reconnect maybe later...

You need to start your socket listener in its own thread, and you need to add a window close listener that shuts down that thread.
For example:
private ServerSocket serverSocket = null;
private boolean done = false;
private void startServer() {
Thread t = new Thread(new Runnable() {
public void Run() {
socketConnection();
});
}
t.start();
}
private void socketConnection() {
try {
serverSocket = new ServerSocket(9090);
System.out.println("Listening: " + serverSocket.getLocalPort());
while (!done) {
try {
final Socket socket = serverSocket.accept();
Thread t = new Thread(new Runnable() {
public void Run() {
handle(socket);
}
});
t.start();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void handle(Socket socket) {
if (socket == null) return;
try {
dataInputStream = new DataInputStream(socket.getInputStream());
System.out.println("ip: " + socket.getInetAddress());
System.out.println("message: " + dataInputStream.readUTF());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void windowClosing(WindowEvent e) {
done = true;
socketServer.close();
}
Your button click listener should call startServer(), then your window close function would set done = true and call socketServer.close().
Now you have one thread for the UI, one thread for the socket server, and one thread for each connection to the server.

Related

Using SwingWorker for client/server application stops handling requests after 10 threads

I have a server project and a client project (2 clients, a customer and an admin, from the customer GUI/Frame you can go to the admin GUI and move between GUIs as needed).
I have a button on each GUI/Frame which just sends a String to the server when it's clicked. I'm printing out the threads that are being created and I know that SwingWorkers Thread pool defaults to 10, and then it starts reusing threads.
I've noticed that once the created Threads hit 10, then the buttons to send requests to the server do not seem to send any data because the Thread pool is fully occupied.
I wanted to know how I can prevent this so a user can switch between the GUIs for x amount of time.
--
Server
public class Testserver {
private ServerSocket serverSocket;
private Socket client;
private final int PORT = 5432;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
public Testserver() {
System.out.println(Thread.currentThread().getName());
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Waiting for connection");
} catch (IOException ex) {
Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void listenForClients() {
try {
while (true) {
client = serverSocket.accept();
System.out.println("client connected");
objectOutputStream = new ObjectOutputStream(client.getOutputStream());
objectInputStream = new ObjectInputStream(client.getInputStream());
processClient();
}
} catch (IOException ex) {
Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Testserver().listenForClients();
});
}
private void processClient() {
SwingWorker worker = new SwingWorker<>() {
#Override
protected Void doInBackground() throws Exception {
System.out.println(Thread.currentThread().getName());
do {
try {
String messageFromClient = (String) objectInputStream.readObject();
System.out.println("[CLIENT] " + messageFromClient);
} catch (IOException ex) {
Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
}
} while (true);
}
};
worker.execute();
}
}
Customer Client
public class CustomerGUI extends JFrame implements ActionListener{
private Socket server;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
private JButton btnAdminGUI,btnAddCustomer;
private final int PORT = 5432;
public CustomerGUI() {
btnAdminGUI = new JButton("Go to Admin GUI");
btnAddCustomer = new JButton("Add customer");
try {
server = new Socket("localhost", PORT);
System.out.println("Connected to server");
objectOutputStream = new ObjectOutputStream(server.getOutputStream());
objectInputStream = new ObjectInputStream(server.getInputStream());
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
btnAdminGUI.addActionListener(this);
btnAddCustomer.addActionListener(this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new CustomerGUI().setGUI();
});
}
public void setGUI() {
setLayout(new GridLayout(2,1));
add(btnAdminGUI);
add(btnAddCustomer);
setSize(300, 400);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnAdminGUI) {
new AdminGUI().setGUI();
dispose();
} else if(e.getSource() == btnAddCustomer) {
try {
objectOutputStream.writeObject("Added a customer");
objectOutputStream.flush();
} catch (IOException ex) {
Logger.getLogger(AdminGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Admin Client(Pretty much the same as Customer)
public class AdminGUI extends JFrame implements ActionListener{
private Socket server;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
private JButton btnCustomerGUI, btnAddAdmin;
private final int PORT = 5432;
public AdminGUI() {
btnCustomerGUI = new JButton("Go to Customer GUI");
btnAddAdmin = new JButton("Add admin");
try {
server = new Socket("localhost", PORT);
System.out.println("Connected to server");
objectOutputStream = new ObjectOutputStream(server.getOutputStream());
objectInputStream = new ObjectInputStream(server.getInputStream());
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
btnAddAdmin.addActionListener(this);
btnCustomerGUI.addActionListener(this);
}
public void setGUI() {
setLayout(new GridLayout(2,1));
add(btnCustomerGUI);
add(btnAddAdmin);
setSize(300, 400);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnCustomerGUI) {
new CustomerGUI().setGUI();
dispose();
} else if(e.getSource() == btnAddAdmin) {
try {
objectOutputStream.writeObject("Added an admin");
objectOutputStream.flush();
} catch (IOException ex) {
Logger.getLogger(AdminGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
EDIT
Updated working method code using FixedThreadPool
private void processClient() {
System.out.println("cores: " + Runtime.getRuntime().availableProcessors());
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
executor.execute(() -> {
System.out.println(Thread.currentThread().getName());
do {
try {
String messageFromClient = (String) objectInputStream.readObject();
System.out.println("[CLIENT] " + messageFromClient);
if (messageFromClient.equalsIgnoreCase("Exit")) {
System.out.println("closed connection to " + client);
closeConnections();
System.exit(0);
}
} catch (IOException ex) {
//JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
//JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
System.out.println("ClassNotFoundException in process client: " + ex.getMessage());
} catch (Exception ex) {
ex.printStackTrace();
//JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
System.out.println("Exception in process client: " + ex.getMessage());
}
} while (true);
});
executor.shutdown();
}

Java how do I use an incoming socket from the client several times

So my question is when a socket connects is it possible to create two datainputstreams which both reference to 1 socket inputstream. I would like to print out text and text2 but this does not work.
Client code
public static void main(String[] args) {
new Sender();
}
public Sender() {
try {
Socket sock = new Socket("127.0.0.1",1337);
DataOutputStream out = new DataOutputStream(sock.getOutputStream());
out.writeUTF("Test");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Server code
public static void main(String[] args) {
new Listen();
}
public Listen() {
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run() {
try {
ServerSocket serversocket = new ServerSocket(1337);
while(true) {
Socket socket = serversocket.accept();
System.out.println(socket.getPort() + ": " + socket.getInetAddress().getHostAddress());
DataInputStream input = new DataInputStream(socket.getInputStream());
DataInputStream input2 = new DataInputStream(socket.getInputStream());
String text = input.readUTF();
String text2 = input2.readUTF();
if(text != null) {
System.out.println(text);
}
if(text2 != null) {
System.out.println(text2);
}
//socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Error");
}
You need a loop, that terminates on EOFException. And don't write code like this. Code that depends on the success of code in a prior try block should be inside that try block.
input = new DataInputStream(socket.getInputStream());
while(!formclosed) {
try {
String addtext = input.readUTF();
addtext = formatText(addtext);
logarea.setText(logarea.getText() + addtext);
} catch (EOFException e) {
System.out.println("Client has disconnected.");
return;
}
}
// any other IOException should be treated as an error
This should run as a background thread, not when you press a button.

android.os.NetworkOnMainThreadException but my class extends Thread

I have a client class that extends Thread to start socket programming
my class code
class MyClientMessages extends Thread {
Socket socket;
int PORT = 5002;
DataInputStream din;
DataOutputStream dout;
public MyClientMessages(String IP) {
try {
System.out.println("IP = ======= " + IP + " TYPE = " + TYPE);
//*********** crash here ***************
socket = new Socket(IP,PORT); // *********** it crash here *************
din = new DataInputStream(socket.getInputStream());
dout = new DataOutputStream(socket.getOutputStream());
this.start();
}catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
while (true) {
byte[] data = new byte[1024];
int size = 0;
try {
while ((size = din.read(data)) > 0) {
final String str = new String(data,"UTF8");
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView textView = new TextView(ServerChat.this);
textView.setTextSize(15);
textView.setText(str);
linearLayout.addView(textView);
}
});
}
}catch (IOException e) {
e.printStackTrace();
try {
dout.close();
din.close();
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
public void WriteToSocket(byte[] arr,int size) {
try {
dout.write(arr,0,size);
dout.flush();
}catch (IOException e) {
e.printStackTrace();
try {
dout.close();
din.close();
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
I make this class inside my activity class. I have another class inside my activity class for server, which extends thread and it works fine. Why does this client class crash and give me this error ?
this how I use it on my onCreate() function:
if (TYPE == 1) {
serverMessages = new MyServerMessages(5002);
Toast.makeText(this,"Room Started Wait clients To Join",Toast.LENGTH_LONG).show();
}
else {
clientMessages = new MyClientMessages(deConvert(mycode)); // crash here
Toast.makeText(this,"Connect To Room",Toast.LENGTH_LONG).show();
}
why this client class crash and give me this error ?
Because you are creating a Socket and opening it in the constructor. Move that logic into run().

Java Send custom object via socket Client, Server, LAN

I want to send object (custom class) via socket from Client to Server. This is my code:
Server:
private class SocketServerThread extends Thread {
#Override
public void run() {
try {
serverSocket = new ServerSocket(socketServerPORT);
while (true) {
clientSocket = serverSocket.accept();
ObjectInputStream inObject = new ObjectInputStream(
clientSocket.getInputStream());
try {
Te xxx = (Te) inObject.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//DataInputStream dataInputStream = new DataInputStream(
//clientSocket.getInputStream());
//messageFromClient=dataInputStream.readUTF();
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
//activity.msgFromC.setText(messageFromClient);
}
});
}
}
Client:
public Client(String aIPaddres, int aPort, Te u) {
AddressIP = aIPaddres;
Port = aPort;
sendUser = u;
}
protected Void doInBackground(Void... arg0) {
Socket clientSocket = null;
try {
clientSocket = new Socket(AddressIP, Port);
ObjectOutputStream outObject = new ObjectOutputStream(
clientSocket.getOutputStream());
outObject.writeObject(sendUser);
//DataOutputStream daneWyjsciowe = new DataOutputStream(
//clientSocket.getOutputStream());
//daneWyjsciowe.writeUTF("Czesc!" );
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//response = "IOException: " + e.toString();
} finally {
if (clientSocket != null) {
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
Custom class (Te.class):
public class Te implements Serializable {
public String message;
public Te(String m){
message=m;
}
}
When I passing simple data i.e. String there is no problem. But now I want to pass object, but there is always ClassNotFoundException at server. I read lot of stacks but I didnt find answer. Could U help me?

Running from jar files gives EOFException

I am trying to create a simple messenger application between two computers, client to server. I have created the necessary port forwards. I have two programs - one for the server and one for the client - when I test them both on my machine from my IDE (Netbeans) they work (the streams are established and I am able to send messages to and fro). But when I run the jar files (again on the same computer) the streams are established between the two programs but then are immediately disconnected since and EOFException is given.
Below please find the code in the Client program and after that the Server program
Client Program
public class ClientGUI extends javax.swing.JFrame {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private final String serverIP = "46.11.85.22";
private Socket connection;
Sound sound;
int idx;
File[] listOfFiles;
String songs[];
public ClientGUI() {
super("Client");
initComponents();
this.setVisible(true);
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
new Thread() {
#Override
public void run() {
try {
startRunning();
} catch (Exception e) {
System.out.println(e);
}
}
}.start();
}
public void startRunning() {
try {
connectToServer();
setupStreams();
whileChatting();
} catch (EOFException e) {
showMessage("\n " + (jtfUsername.getText()) + " terminated connection");
} catch (IOException IOe) {
IOe.printStackTrace();
} finally {
close();
}
}
private void connectToServer() throws IOException {
showMessage("Attempting Connection... \n");
connection = new Socket(InetAddress.getByName(serverIP), 8080);
showMessage("Connected to: " + connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nStreams Estabished \n");
}
private void whileChatting() throws IOException {
ableToType(true);
do {
try {
message = (String) input.readObject();
File folder = new File("src/Files/");
listOfFiles = folder.listFiles();
songs = new String[listOfFiles.length];
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
songs[i] = listOfFiles[i].getAbsolutePath();
}
}
idx = new Random().nextInt(songs.length);
String clip = (songs[idx]);;
sound = new Sound(clip);
sound.play();
showMessage("\n" + message);
} catch (ClassNotFoundException e) {
showMessage("\n Exception occoured");
}
} while (!message.equals("SERVER - END"));
System.exit(0);
}
private void close() {
showMessage("\n Closing Application");
ableToType(false);
try {
output.close();
input.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendMessage(String message) {
try {
output.writeObject(jtfUsername.getText() + " - " + message);
output.flush();
showMessage("\n" + jtfUsername.getText() + " - " + message);
} catch (IOException e) {
jtaView.append("\n Exception Occoured");
}
}
private void showMessage(final String m) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
jtaView.append(m);
}
}
);
}
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
jtfSend.setEditable(tof);
}
}
);
}
Server Program
public class ServerGUI extends javax.swing.JFrame {
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
Sound sound;
int idx;
File[] listOfFiles;
String songs[];
public ServerGUI() {
super("Server");
this.setVisible(true);
initComponents();
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
new Thread() {
#Override
public void run() {
try {
startRunning();
} catch (Exception e) {
System.out.println(e);
}
}
}.start();
}
public void startRunning() {
try {
server = new ServerSocket(8080, 10);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (EOFException e) { // End of Stream
showMessage("\n Server ended the connection!");
} finally {
close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void waitForConnection() throws IOException {
showMessage("Waiting for client to connect... \n");
connection = server.accept();
showMessage("Now connected to " + connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nStreams are setup \n");
}
private void whileChatting() throws IOException {
String message = "You are now connected!";
sendMessage(message);
ableToType(true);
do {
try {
message = (String) input.readObject();
File folder = new File("src/Files/");
listOfFiles = folder.listFiles();
songs = new String[listOfFiles.length];
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
songs[i] = listOfFiles[i].getAbsolutePath();
}
}
idx = new Random().nextInt(songs.length);
String clip = (songs[idx]);
sound = new Sound(clip);
sound.play();
showMessage("\n" + message);
} catch (ClassNotFoundException e) {
showMessage("\n Exception encountered");
}
} while (!message.contains("END"));
shutdown();
}
private static void shutdown() throws IOException {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("shutdown -s -t 30");
System.exit(0);
}
private void close() {
showMessage("\n Closing connections... \n");
ableToType(false);
try {
output.close();
input.close();
connection.close();
} catch (IOException ioE) {
ioE.printStackTrace();
}
}
private void sendMessage(String message) {
try {
output.writeObject("SERVER - " + message);
output.flush();
showMessage("\nSERVER - " + message);
} catch (IOException ioE) {
jtaView.append("\n ERROR Sending");
}
}
private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
jtaView.append(text);
}
}
);
}
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
jtfSend.setEditable(tof);
}
}
);
}
I asked my computing teacher and he told me that it might be the ports that I'm using but it still didn't work with these ports when executing the jar files. Any ideas?

Categories