Java ObjectInputStream(Socket Socket) перезапускает все приложение?

Поэтому я делаю Java-сервер и клиент.

В настоящее время мой клиент подключается к серверу и создает входные и выходные потоки объектов для клиентской и серверной сторон.

Сразу же, когда я пытаюсь получить данные через этот ObjectInputStream(сокет Socket) сервера, он перезапускает всю программу.

Даже не упоминается ни об ошибках, ни исключениях, ни о других? Клиент говорит: "Сервер закрыл соединение: java.net.SocketException: сокет закрыт" <- поэтому Сервер также закрывает сокет и все, что с ним связано.

Вот мой Сервер и Клиент (+ Бонусный вопрос: Если в Сервере и Клиенте есть разные именованные объекты, но способ создания этих объектов одинаков, могу ли я отправлять и читать их через сокет?)

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) {}
        }
    }
}

и клиент:

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 ответ

Клиент говорит: "Сервер закрыл соединение: java.net.SocketException: сокет закрыт"

Это ваше сообщение, и оно не правильно. Вы предполагаете, что каждый IOException означает, что сервер закрыл соединение. Это конечно не так. Единственные два исключения, которые действительно означают, что EOFException и, как правило, IOException: connection reset,

Это конкретное исключение SocketException: socket closed, и это означает, что вы, клиент, закрыли соединение, а затем продолжили его использовать. Например, если ваш первоначальный вход не выполнен, вы отключаетесь, но ваш поток слушателя все еще работает, пытаясь прочитать.

Не вводите себя в заблуждение, делая ложные предположения, и особенно не встраивайте их в свои сообщения об ошибках.

NB:

  1. Вам нужно создать ObjectOutputStream до ObjectInputStream.

  2. Ваш поток слушателя должен поймать EOFException и вырваться из петли, когда он пойман.

Другие вопросы по тегам