Jtvd78
Jtvd78

Reputation: 4250

Server reply to Client message failing due to closed socket - Java Client-Server example

I'm creating this little client-server program to learn about sockets, and so far, I'm having a bit of trouble. For the purpose of this post, I consolidated the code into a single class. And the code will compile. (So it will show the same errors I get)

When the client connects to the server, the server socket properly creates a socket on the server-side. The Client then successfully sends a message to the server, but when the server tries to send a response to the client, there is an error saying the socket is closed.

Main.java

package main;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Hashtable;

public class Main {

    boolean running = true;

    public static void main(String[] args){
        new Main().start();
    }

    public void start(){
        new Thread(new ConnectionListener()).start(); //Starts Server
        try {
            connectToServer();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public class ConnectionListener implements Runnable{    
        public void run() {
            ServerSocket ss = null;

            try {
                ss  = new ServerSocket(31415);
            }catch (BindException e) {
                e.printStackTrace();
                return;
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }

            while(running){
                try {
                    Socket sock = ss.accept();
                    ServerConnection c = new ServerConnection(sock);
                    c.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void connectToServer() throws UnknownHostException, IOException{
        //Create Connection to Server
        Socket socket = new Socket("localhost",31415);
        ClientConnection cc = new ClientConnection(socket); 
        cc.start();

        //Send First Message to Server
        Hashtable<Integer, String> htt = new Hashtable<Integer, String>();
        htt.put(0,"Hello, This is a Chat Test");

        Message m = new Message(Message.Type.CHAT,htt);
        cc.sendMessage(m);
    }

    public class ServerConnection{
        Socket sock;
        boolean connected = true;

        public ServerConnection(Socket sock){
            this.sock = sock;
        }

        public void start() {
            new Thread(new RequestListener()).start();
        }

        private void handleMessage(Message m){
            System.out.println("Server : Handle message " + m.type.toString());
        }

        public void disconnect(){
            System.out.println("Disconnect user");
        }

        public void sendMessage(Message m){
                try {
                    ObjectOutputStream os = new ObjectOutputStream(sock.getOutputStream());
                    os.writeObject(m);
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

        class RequestListener implements Runnable{

            public void run() {

                ObjectInputStream is = null;

                try {
                    is = new ObjectInputStream(sock.getInputStream()); 

                    while(connected){
                        try {
                            Message m = (Message)
                                    is.readObject(); //EOFException
                            handleMessage(m);
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }catch(SocketException e){
                            disconnect();
                            e.printStackTrace();
                            break;

                        }catch (IOException e) {
                            //e.printStackTrace();  //EOFException Here
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }finally{
                    try {
                        is.close();

                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public class ClientConnection {

        private Socket socket;
        private boolean connected = true;

        public ClientConnection(Socket socket) {
            this.socket = socket;
        }

        public void start(){
            new Thread(new RequestListener()).start();
        }

        public void sendMessage(Message m){
            try {
                ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
                os.writeObject(m);
                os.flush();
                os.close();
            } catch (IOException e) {
                System.out.println("Error Sending Message");
                e.printStackTrace();
            }
        }

        public void close() throws IOException{
            Message m = new Message(Message.Type.DISCONNECT,null);
            sendMessage(m);
            socket.close();
        }

        private void handleMessage(Message m){
            System.out.println("Client : Handle message " + m.type.toString());
        }

        class RequestListener implements Runnable{

            public void run() {

                ObjectInputStream is = null;

                try {

                    System.out.println(socket.isConnected()); //true
                    System.out.println(socket.isClosed()); //false
                    InputStream iss = socket.getInputStream();
                    is = new ObjectInputStream(iss);  //socketClosedException

                    while(connected){
                        try {
                            Message m = (Message)is.readObject();
                            handleMessage(m);
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }catch(SocketException e){

                            System.out.println("Server Disconnected");
                            break;

                        }catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }finally{
                    try {
                        is.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }   
}

Message.java

package main;

import java.io.Serializable;
import java.util.Hashtable;

public class Message implements Serializable{

    public enum Type{
        LOGIN, PM, DISCONNECT, INCORRECT_LP,CORRECT_LP, UPDATE_USERLIST, CHAT, INCORRECT_VERSION
    }

    public Type type;
    Hashtable ht;

    public Message(Type type, Hashtable ht){
        this.type = type;
        this.ht = ht;
    }

    public Object get(Object o){
        return ht.get(o);
    }
}

Upvotes: 0

Views: 875

Answers (1)

user207421
user207421

Reputation: 310859

There's nothing 'random' about it.

Closing the input or output stream of a Socket closes the other stream and the Socket.

In this case you are closing the ObjectOutputStream you have wrapped around the socket's output stream, which closes that output stream, which closes the socket's input stream and the socket.

Upvotes: 1

Related Questions