8 Replies - 2869 Views - Last Post: 03 December 2013 - 12:51 PM Rate Topic: -----

#1 bubblerfett   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 26
  • Joined: 11-November 13

how do I catch a connection reset error

Posted 02 December 2013 - 11:14 PM

I am trying to make a multi threaded chat server and when I exit a client, it throws this error
java.net.SocketException: Connection reset
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
	at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
	at sun.nio.cs.StreamDecoder.read(Unknown Source)
	at java.io.InputStreamReader.read(Unknown Source)
	at java.io.BufferedReader.fill(Unknown Source)
	at java.io.BufferedReader.readLine(Unknown Source)
	at java.io.BufferedReader.readLine(Unknown Source)
fail read message
	at Server$ClassHandler.run(Server.java:72)
	at java.lang.Thread.run(Unknown Source)


here is my server
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

public class Server {
	ArrayList<PrintWriter> writers; // hold a list of current connections
	private ServerSocket serverSocket;
	private static SimpleDateFormat date = new SimpleDateFormat(
			"dd/mm/yyyy hh:mm:ss");
	private static Calendar cal = Calendar.getInstance();

	public static void main(String[] args) {
		new Server().go();
	}

	public void go() {
		try {
			// setup port listener
			// add connections to arraylist
			// setup in and out streams
			System.out.println("waiting connetion");
			serverSocket = new ServerSocket(8999);
			writers = new ArrayList<PrintWriter>();
			while (true) {
				Socket clientSocket = serverSocket.accept();
				PrintWriter writer = new PrintWriter(
						clientSocket.getOutputStream());
				writers.add(writer);
				Thread t = new Thread(new ClassHandler(clientSocket));
				t.start();
				System.out.println("connected");
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			System.out.println("fail setup network");

		}
	}

	class ClassHandler implements Runnable {
		private BufferedReader in;

		public ClassHandler(Socket sock) {
			// setup a client connection
			try {
				in = new BufferedReader(new InputStreamReader(
						sock.getInputStream()));
			} catch (IOException e) {
				e.printStackTrace();

				System.out.println("fail classhandler");
			}
		}

		@Override
		public void run() {
			// receive and relay messages back to clients
			String message;
			try {
				while ((message = in.readLine()) != null) {
					shout(message);
					System.out.println("client says : "
							+ date.format(cal.getTime()) + message);
				}
			} catch (IOException ex) {
				ex.printStackTrace();
				System.out.println("fail read message");

			}
		}

		public synchronized void shout(String message) {
			// send message to all clients
			for (PrintWriter writer : writers) {
				writer.println(date.format(cal.getTime()) + " " + message
						+ "\n");
				writer.flush();
			}
		}

	}

}


and here is my client
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Client {

	private JTextArea tArea;
	private BufferedReader in;
	private Socket sock;
	private PrintWriter out;
	private static String name;

	public static void main(String[] args) {
		System.out.println("Enter username");
		Scanner input = new Scanner(System.in);
		name = input.nextLine();
		input.close();
		new Client().go();

	}

	public void go() {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				JFrame frame = new JFrame("Chat Client");
				final JTextField tField = new JTextField(25);
				tArea = new JTextArea(30, 20);
				tArea.setEditable(false);
				JButton button = new JButton("send");
				button.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent ev) {
						sendMessage(tField.getText());
						tField.setText("");
					}
				});
				frame.setSize(300, 500);
				frame.setVisible(true);
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.add(tArea, BorderLayout.NORTH);
				frame.add(tField, BorderLayout.CENTER);
				frame.add(button, BorderLayout.EAST);
				frame.pack();
			}
		});
		setupNetwork();
		Thread t = new Thread(new IncomingReader());
		t.start();
	}

	public void setupNetwork() {
		try {
			sock = new Socket("localhost", 8999);
			in = new BufferedReader(
					new InputStreamReader(sock.getInputStream()));
			out = new PrintWriter(sock.getOutputStream());

		} catch (IOException ex) {
			ex.printStackTrace();
			System.out.println("fail networking");
		}
	}

	class IncomingReader implements Runnable {
		public void run() {
			// receive messages from server
			try {
				String message = null;
				while ((message = in.readLine()) != null) {
					tArea.append(message + "\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("fail incoming reader");

			}
		}
	}

	public synchronized void sendMessage(String message) {
		try {

			out.println("(" + name + ")" + ": " + message);
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("fail send message");
		}
	}
}




I have been trying to think of how to find out a connection as been closed and remove it from the arraylist, but I have no idea, I tried random stuff and have not made any progress.

Is This A Good Question/Topic? 0
  • +

Replies To: how do I catch a connection reset error

#2 g00se   User is online

  • D.I.C Lover
  • member icon

Reputation: 3583
  • View blog
  • Posts: 16,399
  • Joined: 20-September 08

Re: how do I catch a connection reset error

Posted 03 December 2013 - 05:04 AM

You should probably be doing the following:

a. don't save Writers in a List. Save Sockets in a Set
b. 'ClassHandler' (why 'Class'?) - save 'sock' as an instance variable
c. (See below). Better to handle disconnections in an orderly manner, maybe as part of the protocol. Disconnecting is not exceptional
        @Override
        public void run() {
            // receive and relay messages back to clients
            String message;

            try {
                while ((message = in.readLine()) != null) {
                    shout(message);
                    System.out.println("client says : " +
                        date.format(cal.getTime()) + message);
                }
            } catch (SocketException ex) {
                // Assume client disconnected
                // and remove from Set<Socket>
                connections.remove(sock);
            } catch (IOException ex) {
                ex.printStackTrace();
                System.out.println("fail read message");
            }
        }



This post has been edited by g00se: 03 December 2013 - 05:06 AM
Reason for edit:: indent

Was This Post Helpful? 0
  • +
  • -

#3 CasiOo   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1577
  • View blog
  • Posts: 3,551
  • Joined: 05-April 11

Re: how do I catch a connection reset error

Posted 03 December 2013 - 08:39 AM

Also you should make your client disconnect in a good manner
Right now you are cutting off the connection without calling socket.close()
This results in the server getting an unexpect disconnect

Add a WindowListener to your JFrame, so you know when the window is closing
Before closing, you should disconnect the socket if it is connected
Was This Post Helpful? 0
  • +
  • -

#4 g00se   User is online

  • D.I.C Lover
  • member icon

Reputation: 3583
  • View blog
  • Posts: 16,399
  • Joined: 20-September 08

Re: how do I catch a connection reset error

Posted 03 December 2013 - 10:07 AM

Quote

Also you should make your client disconnect in a good manner
Right now you are cutting off the connection without calling socket.close()
That's certainly the case. While it won't help with the original problem (because the disconnect is not happening as part of the protocol) it might well help with lingering sockets in the wrong state on the client OS
Was This Post Helpful? 0
  • +
  • -

#5 bubblerfett   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 26
  • Joined: 11-November 13

Re: how do I catch a connection reset error

Posted 03 December 2013 - 11:41 AM

Thanks for the suggestions, I made some changes but I am still getting the error. My issue is I don't know WHEN to close the connection, and if I do, I don't know how to choose WHICH socket to close, lets say the 5th client closes the app, how do I catch that he closed it and than remove it from the set. Here is some updated code, am i heading in the right direction? I understand I should account for windowlistener, but what if the user loses internet? isn't there a way to catch all disconnects or something on both ends. Also, what is the point of changing to a set instead of an arraylist, I chose arraylist because thats how the book did it.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

public class Server {
	// ArrayList<PrintWriter> writers; // hold a list of current connections
	Set<Socket> sockets = new HashSet<Socket>();
	private ServerSocket serverSocket;
	private Socket sock;
	private static SimpleDateFormat date = new SimpleDateFormat(
			"dd/mm/yyyy hh:mm:ss");
	private static Calendar cal = Calendar.getInstance();

	public static void main(String[] args) {
		new Server().go();
	}

	public void go() {
		try {
			// setup port listener
			// add connections to arraylist
			// setup in and out streams
			System.out.println("waiting connetion");
			serverSocket = new ServerSocket(8999);
			// writers = new ArrayList<PrintWriter>();

			while (true) {
				sock = serverSocket.accept();
				sockets.add(sock);
				// PrintWriter writer = new PrintWriter(
				// sock.getOutputStream());
				// writers.add(writer);
				Thread t = new Thread(new ClientHandler(sock));
				t.start();
				System.out.println("connected");
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			System.out.println("fail setup network");

		} finally {
			System.out.println("finally");

		}
	}

	class ClientHandler implements Runnable {
		private BufferedReader in;

		public ClientHandler(Socket sock) {
			// setup a client connection
			try {
				in = new BufferedReader(new InputStreamReader(
						sock.getInputStream()));
			} catch (IOException e) {
				e.printStackTrace();

				System.out.println("fail classhandler");
			}
		}

		@Override
		public void run() {
			// receive and relay messages back to clients
			String message;
			try {
				while ((message = in.readLine()) != null) {
					shout(message);
					System.out.println("client says : "
							+ date.format(cal.getTime()) + message);
				}
			} catch (IOException ex) {
				try {
					System.out.println("closing");
					sock.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				sockets.remove(sock);
				System.out.println(sockets);
				ex.printStackTrace();
				System.out.println("fail read message");

			}
		}

		public synchronized void shout(String message) {
			// send message to all clients
			// for (PrintWriter writer : writers) {
			// writer.println(date.format(cal.getTime()) + " " + message
			// + "\n");
			// writer.flush();
			// }
			for (Socket sock : sockets) {
				try {
					PrintWriter writer = new PrintWriter(sock.getOutputStream());
					writer.println(date.format(cal.getTime()) + " " + message
							+ "\n");
					writer.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}

		}

	}

}


Was This Post Helpful? 0
  • +
  • -

#6 g00se   User is online

  • D.I.C Lover
  • member icon

Reputation: 3583
  • View blog
  • Posts: 16,399
  • Joined: 20-September 08

Re: how do I catch a connection reset error

Posted 03 December 2013 - 12:00 PM

Quote

I don't know how to choose WHICH socket to close, lets say the 5th client closes the app, how do I catch that he closed it and than remove it from the set.
You seem to have missed my post ...
Was This Post Helpful? 0
  • +
  • -

#7 bubblerfett   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 26
  • Joined: 11-November 13

Re: how do I catch a connection reset error

Posted 03 December 2013 - 12:15 PM

my new code shows your changes, I still get the error, unless I did it wrong

 public void run() {
071
            // receive and relay messages back to clients
072
            String message;
073
            try {
074
                while ((message = in.readLine()) != null) {
075
                    shout(message);
076
                    System.out.println("client says : "
077
                            + date.format(cal.getTime()) + message);
078
                }
079
            } catch (IOException ex) {
080
                try {
081
                    System.out.println("closing");
082
                    sock.close();
083
                } catch (IOException e) {
084
                    e.printStackTrace();
085
                }
086
                sockets.remove(sock);
087
                System.out.println(sockets);
088
                ex.printStackTrace();
089
                System.out.println("fail read message");
090
 
091
            }
092
        }



Someone else also told me to change it in the run but this is why I am confused, according to the way its written it says if I receive null I should close and remove the socket, which it seems to do, but the error is not going away
Was This Post Helpful? 0
  • +
  • -

#8 bubblerfett   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 26
  • Joined: 11-November 13

Re: how do I catch a connection reset error

Posted 03 December 2013 - 12:39 PM

hm this is weird, I started over a bit and now the error is gone, I don't know what caused it to go away though, however here is my final code as of now that seems to be working correctly
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Server {
	// ArrayList<PrintWriter> writers; // hold a list of current connections
	Set<Socket> sockets = new HashSet<Socket>();
	private ServerSocket serverSocket;
	private Socket sock;
	private static int port;
	private static SimpleDateFormat date = new SimpleDateFormat(
			"dd/mm/yyyy hh:mm:ss");
	private static Calendar cal = Calendar.getInstance();

	public Server(int choice) {
		port = choice;
	}

	public static void main(String[] args) {
		System.out.println("enter a port");
		Scanner input = new Scanner(System.in);
		port = input.nextInt();
		new Server(port).go();
		input.close();
	}

	public void go() {
		try {
			// setup port listener
			// add connections to arraylist
			// setup in and out streams
			System.out.println("waiting connetion");
			serverSocket = new ServerSocket(port);
			// writers = new ArrayList<PrintWriter>();

			while (true) {
				sock = serverSocket.accept();
				sockets.add(sock);
				// PrintWriter writer = new PrintWriter(
				// sock.getOutputStream());
				// writers.add(writer);
				Thread t = new Thread(new ClientHandler(sock));
				t.start();
				System.out.println("connected");
				System.out.println(sockets);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			System.out.println("fail setup network");

		} finally {
			System.out.println("finally");

		}
	}

	class ClientHandler implements Runnable {
		private BufferedReader in;

		public ClientHandler(Socket sock) {
			// setup a client connection
			try {
				in = new BufferedReader(new InputStreamReader(
						sock.getInputStream()));
			} catch (IOException e) {
				e.printStackTrace();

				System.out.println("fail classhandler");
			} 
		}

		@Override
		public void run() {
			// receive and relay messages back to clients
			String message;
			try {
				while ((message = in.readLine()) != null) {
					shout(message);
					System.out.println("client says : "
							+ date.format(cal.getTime()) + message);
				}
			} catch (IOException ex) {
				System.out.println(sockets);
				System.out.println("user disconnected");
				try {
					sock.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				sockets.remove(sock);
			}
		}

		public synchronized void shout(String message) {
			// send message to all clients
			// for (PrintWriter writer : writers) {
			// writer.println(date.format(cal.getTime()) + " " + message
			// + "\n");
			// writer.flush();
			// }
			for (Socket sock : sockets) {
				try {
					PrintWriter writer = new PrintWriter(sock.getOutputStream());
					writer.println(date.format(cal.getTime()) + " " + message
							+ "\n");
					writer.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}

		}

	}

}



Was This Post Helpful? 0
  • +
  • -

#9 g00se   User is online

  • D.I.C Lover
  • member icon

Reputation: 3583
  • View blog
  • Posts: 16,399
  • Joined: 20-September 08

Re: how do I catch a connection reset error

Posted 03 December 2013 - 12:51 PM

Quote

    } catch (SocketException ex) {
        // Assume client disconnected
        // and remove from Set<Socket>
        connections.remove(sock);

I don't see much of that in your code...
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1