0
votes

So I'm making a java Server and Client.

Currently my Client connects to the server and creates Object input and Output streams for both client and server side.

Immediately when I try to receive data over that ObjectInputStream(Socket socket) of Server it restarts the whole program.

It doesen't even mention about any errors or exceptions or others? Client says: "Server has closed the connection: java.net.SocketException: socket closed" <- so Server also closes the socket and everything related to it.

Here's my Server and Client (+ Bonus question: If there are different named objects in Server and Client but the way those objects are made are the same, can I send and read those over socket?)

package com.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import com.gui.Screen;
import com.gui.TextArea;

public class Server implements Runnable{
//Every connection got their own unique id
private static int uniqueId;
//List all the clients
private static ArrayList<ClientThread> al;
private static boolean running = false;
@SuppressWarnings("unused")
private SimpleDateFormat sdf;
ServerSocket serverSocket;

public Server(int port) {
    sdf = new SimpleDateFormat("HH:mm:ss");
    al = new ArrayList<ClientThread>();
}

public void run() {
    running = true;
    try {
        serverSocket = new ServerSocket(Screen.portnumber);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        //Server socket
        TextArea.AddLine("Server is running and waiting for Clients to connect.");
        while(running){
            Socket socket = serverSocket.accept();
            ClientThread t = new ClientThread(socket);
            al.add(t); //saving new client to our arraylist.
            t.run();
            if(!running){ //this will make server running stop.
                TextArea.AddLine("Closing the server..");
                break;
            }
        }
        for(int i = 0; i< al.size(); i++){//We forget about all the clients.
            //Maybe also save all the data here?
            ClientThread tc = al.get(i);
            try{
            tc.sInput.close();
            tc.sOutput.close();
            tc.socket.close();
            }
            catch(IOException ioE){

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

public static void close() {
    running = false;
    try {
        new Socket("localhost", Screen.portnumber);
    } catch (Exception e) { TextArea.AddLine("Can't disconnect.."); }
}

    synchronized void remove(int id) {
        // scan the array list until we find the Id
        for(int i = 0; i < al.size(); ++i) {
            ClientThread ct = al.get(i);
            // found it
            if(ct.id == id) {
                al.remove(i);
                return;
            }
        }
    }

public static boolean isRunning(){
    return running;
}

    class ClientThread extends Thread {
        //The socket where to listen/talk
        Socket socket;
        ObjectInputStream sInput;
        ObjectOutputStream sOutput;
        //my unique id (easier for deconnection)
        int id;
        //Objects that we will be receiving
        Incomingdata datain;
        //the date we connect
        String date;
        Player player;

        //Constructor
        ClientThread(Socket socket){
            id = uniqueId++;
            this.socket = socket;
            try{
                sOutput = new ObjectOutputStream(socket.getOutputStream());
                sInput = new ObjectInputStream(socket.getInputStream());
            } catch (Exception e){
                System.out.println("Couldn't create Input/Output streams");
            }
            date = new Date().toString();
        }

        // what will run forever
        public void run() {
            // to loop until LOGOUT
            boolean Connected = true;
            while(Connected) {
                // Read incoming data
                try {
                    //Everything works until that
                    datain = (Incomingdata) sInput.readObject();
                    //at this point the program restarts?
                }
                catch (IOException e) {
                    TextArea.AddLine(Incomingdata.getUsername(datain) + " Exception reading Streams: " + e);
                    break;              
                }
                catch(ClassNotFoundException e2) {
                    break;
                }
                if(datain != null){
                    // Switch on the type of message receive
                    switch(Incomingdata.getAction(datain).getType()) {

                    case 0://Log off
                        TextArea.AddLine(Player.getUsername(player) + " logged off.");
                        Connected = false;
                        break;
                    case 1://Talk
                        TextArea.AddLine(Incomingdata.getUsername(datain) + ": " +Incomingdata.getAction(datain).getString());
                        break;
                    case 2://Move
                        Player.move(player);
                    }
                }
            }
            // remove myself from the arrayList containing the list of the
            // connected Clients
            remove(id);
            close();
        }

        // try to close everything
        private void close() {
            // try to close the connection
            try {
                if(sOutput != null) sOutput.close();
            }
            catch(Exception e) {}
            try {
                if(sInput != null) sInput.close();
            }
            catch(Exception e) {};
            try {
                if(socket != null) socket.close();
            }
            catch (Exception e) {}
        }
    }
}

and Client:

package com.connection;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Client {

// for I/O
private ObjectInputStream sInput;       // to read from the socket
private static ObjectOutputStream sOutput;      // to write on the socket
private Socket socket;
private Outgoingdata lastdata;
private Outgoingdata currentdata;
static Client client;
public static boolean connected = false;
public static Player player;

String server;
int port;

Client(String server, int port) {
    this.server = server;
    this.port = port;
}

/*
 * When something goes wrong
 * Close the Input/Output streams and disconnect not much to do in the catch clause
 */
private void disconnect() {
    try { 
        if(sInput != null) sInput.close();
    }
    catch(Exception e) {} // not much else I can do
    try {
        if(sOutput != null) sOutput.close();
    }
    catch(Exception e) {} // not much else I can do
    try{
        if(socket != null) socket.close();
    }
    catch(Exception e) {} // not much else I can do
}

public boolean start() {
    // try to connect to the server
    try {
        socket = new Socket(server, port);
    } 
    // if it failed not much I can so
    catch(Exception ec) {
        System.out.println("Error connectiong to server:" + ec);
        return false;
    }

    System.out.println("Connection accepted " + socket.getInetAddress() + ":" + socket.getPort());

    /* Creating both Data Stream */
    try
    {
        sInput  = new ObjectInputStream(socket.getInputStream());
        sOutput = new ObjectOutputStream(socket.getOutputStream());
    }
    catch (IOException eIO) {
        System.out.println("Exception creating new Input/output Streams: " + eIO);
        return false;
    }

    // creates the Thread to listen from the server 
    new ListenFromServer().start();
    // Send our username to the server this is the only message that we
    // will send as a String. All other messages will be ChatMessage objects
    try
    {
        sOutput.writeObject(new Incomingdata("minisurma", "kaikim", null));
    }
    catch (IOException eIO) {
        System.out.println("Exception doing login : " + eIO);
        disconnect();
        return false;
    }
    // success we inform the caller that it worked
    return true;
}

public static void Connect() {
    // default values
    int portNumber = 1500;
    String serverAddress = "localhost";

    // create the Client object
    client = new Client(serverAddress, portNumber);
    // test if we can start the connection to the Server
    // if it failed nothing we can do
    if(!client.start())
        return;
    connected = true;
}

public static void Disconnect() {
    connected = false;
    client.disconnect();
}

class ListenFromServer extends Thread {

    public void run() {
        while(true) {
            try {
                Outgoingdata data = (Outgoingdata) sInput.readObject();
                System.out.println("data");
            }
            catch(IOException e) {
                System.out.println("Server has closed the connection: " + e);
            }
            // can't happen with a String object but need the catch anyhow
            catch(ClassNotFoundException e2) {
            }
        }
    }
}

public static void send(Incomingdata incomingdata) {
    try {
        sOutput.writeObject(incomingdata);
    }
    catch(IOException e) {
        System.out.println("Exception writing to server: " + e);
    }
}
}
1

1 Answers

1
votes

Client says: "Server has closed the connection: java.net.SocketException: socket closed"

That's your message, and it isn't correct. You're assuming that every IOException means that the server closed the connection. This is certainly not so. The only two exceptions that really mean that are EOFException and, usually, IOException: connection reset.

This particular exception is a SocketException: socket closed, and its meaning is that you, the client, closed the connection and then continued to use it. For example, if your initial login fails, you disconnect, but your listener thread is still running, trying to read.

Don't mislead yourself by making false assumptions, and especially don't build them into your error messages.

NB:

  1. You need to create the ObjectOutputStream before the ObjectInputStream.

  2. Your listener thread needs to catch EOFException and break out of the loop when it is caught.