2017-01-11 3 views
0

Ich schreibe ein College-Projekt auf Banking-System für Server - Client-Kommunikation. Eine der Anforderungen ist das OOP-Design einer Anwendung.java.net.SocketException: Socket ist geschlossen OOP Design Bug

Ich habe einen Fehler in der Klasse, wo ich Methoden für die Kommunikation implementieren.

Dies ist ein clientseitiger Code. Server Side ist ähnlich implementiert und erzeugt denselben Fehler.

Das Ergebnis eines Fehlers ist java.net.SocketException: Socket is closed

Klasse, die Kommunikationsmethoden implementiert:

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

          // My custom interface 
public class DriveableImpl implements Driveable{ 

    private Socket socket; 
    private ObjectOutputStream out; 
    private ObjectInputStream in; 

    protected DriveableImpl() {} 

    // Method that set a socket for a current communication instance 
    private void setSocket(Socket socket) { 
     this.socket = socket; 
    } 

    // Method to connect to a server that takes parameters required to open socket 
    @Override 
    public void connect(String ip, int port){ 
     try { 
      socket = new Socket(ip, port); // open new socket 
      setSocket(socket); // set a socket for a current instance to use in other methods 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    // Method to close connection with a server 
    // Oddly, this method is not bugged and can close socket safely 
    @Override 
    public void disconnect(){ 
     sendMessage(0); // send a tag number of a method to a server 
     if(socket != null){ 
      try { 
       System.out.println("Closing socket: " + socket); 
       socket.close(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    // Method produce BUG 
    // Method that accepts any java object as a parameter and send it through a socket of a current instance 
    @Override 
    public void sendMessage(Object message) { 
     try{ 
      out = new ObjectOutputStream(socket.getOutputStream()); // new object stream with a given socket 
      out.writeObject(message); // send an object stream through a socket 
      out.flush(); // flush the stream to insure all data is sent and stream is free for new objects 
      out.close(); // close a stream for current method invocation 
     } 
     catch(IOException ioException){ 
      ioException.printStackTrace(); 
     } 
    } 

    // Method has a BUG 
    // Method that reads objects sent by server through a socket 
    @Override 
    public Object receiveMessage(){ 
     try{ 
      in = new ObjectInputStream(socket.getInputStream()); // creating new stream to read serialized objects from socket stream 
      try { 
       return in.readObject(); // return an object that was read from stream 
      } catch (ClassNotFoundException e) { 
       e.printStackTrace(); 
      } finally{ 
       in.close(); // close the stream when object is read and returned 
      } 
     } catch(IOException ioException){ 
      ioException.printStackTrace(); 
     } 
     return null; // returns null if something went wrong 
    } 

    // Method that produce BUG 
    // Method that processes user registration 
    @Override 
    public void registration(){ 
     sendMessage(2); // send a tag number of a method to a server 

     try { 
      String outcome = (String) receiveMessage(); // waiting for response from server 
      System.out.println(outcome); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // Method that produce BUG 
    // Method that processes user login and returns login status as boolean expression 
    @Override 
    public boolean login(){ 
     sendMessage(1); // send a tag number of a method to a server 

     // Block that receives message from a server about login status, i.e., logged in or reasons for not being logged in 
     try { 
      outcome = (String) receiveMessage(); 
      System.out.println(outcome); 
      return (boolean)receiveMessage(); // method returns boolean (true/false) that is required 
               // to manipulate authentication and issue authorization privileges 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } // waiting for response from server 

     return false; // if something goes wrong, return false 
    } 

} // end of DriveableImpl class 

Dies ist der Standardklasse, die Methoden aufruft und aufgerufenen Methoden zurückgeben zurückgibt:

package ie.gmit.sw.client.methods; 

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

public class MethodInvoker implements InvocationHandler{ 

    private Object returnObject = null; // object that will hold any returns from invoked methods 
    private final Driveable userInterface; 


    protected MethodInvoker(Driveable ui) { 
     this.userInterface = ui; 
    } 
    public Object invoke(Object proxy, Method method, Object[] args) 
        throws IllegalAccessException, IllegalArgumentException, 
        InvocationTargetException{ 

     System.out.println("BEFORE"); 
     returnObject = method.invoke(userInterface, args); 
     System.out.println(method.getName()); 
     System.out.println("AFTER"); 

     return returnObject; 
    } 
} 

Klasse, die zwischen MethodInvoker Klasse und Klasse, die Kommunikationsverfahren implementiert einkapselt Bindung:

package ie.gmit.sw.client.methods; 

import java.lang.reflect.Proxy; 

         // Extending a class that implements Driveable Interface 
         // I thought it's a good use of polymorphism 
         // Used later to create instance of this class of a type Driveable to maximize abstraction 
public class IssueDriver extends DriveableImpl { 

    private DriveableImpl di = new DriveableImpl(); // creating Object with implemented methods that are required to handle 
    private MethodInvoker handler = new MethodInvoker(di); // creating Object that handles/executes methods from implementation class 
    // Creating driver through which methods can be called 
    private final Driveable driver = (Driveable) Proxy.newProxyInstance(Driveable.class.getClassLoader(), 
      new Class[] { Driveable.class }, 
      handler); 

    // Constructor that carries driver object 
    public IssueDriver() { 
     getDriver(); 
    } 

    // returns driver 
    private Driveable getDriver() { 
     return driver; 
    } 
} 

Klasse, die Treiber verwendet Objekt aufzurufen Methoden:

package ie.gmit.sw.client; 

import java.util.Scanner; 

import ie.gmit.sw.client.methods.Driveable; 
import ie.gmit.sw.client.methods.IssueDriver; 

public class UserInterface { 

    private int option; 
    private Scanner input; 
    private Driveable driver; // methods driver object 
    private boolean authenticated = false; // Variable to verify authentication and give corresponding authorization rights. 


    protected UserInterface() { 
     driver = new IssueDriver(); // creating new instance of a methods driver i.e., user options in UI 
    } 

    protected void menu() { 

     input = new Scanner(System.in); 

     try {   /* ip   port*/ 
      driver.connect("localhost", 2017); // Method that connects to a server. Excepts parameters with ip address and port number. 
     } catch (Exception connect) { 
      connect.printStackTrace(); 
     } 


     do{ 

      if(authenticated == false){ 

       System.out.println("Choose from these choices"); 
       System.out.println("-------------------------\n"); 
       System.out.println("1 - Login"); 
       System.out.println("2 - Register"); 
       System.out.println("0 - Quit"); 

       option = input.nextInt(); 
       switch(option){ 
        case 1: System.out.println("Login"); 
          try { 
           authenticated = driver.login(); // Method sends an object with user input for login 
                   // and returns status response from the server. 
          } catch (Exception login) { 
           // TODO Auto-generated catch block 
           login.printStackTrace(); 
          } 

          break; 
        case 2: System.out.println("Registration"); 
          System.out.println(); 
          try { 
           driver.registration(); // Method sends an object with registration data to the server. 
                 // Receives status message from server. 
          } catch (Exception registration) { 
           // TODO Auto-generated catch block 
           registration.printStackTrace(); 
          } 
          break; 
        case 0: System.out.println("Quit"); 
          try { 
           driver.disconnect(); // Method closes connection with server. 
          } catch (Exception discon){ 
           discon.printStackTrace(); 
          } 
          break; 
       } 
      } 
      else if(authenticated == true){ 
        // .... 
      } 

     }while(option != 0);    
    } 
} 

ich versuchte, zu verengen, den Code und isolieren Problem . Die Klasse public class UserInterface wird in einer Ausführungsmethode eines Threads weiter instanziiert, um eine App auszuführen.

Überkoche ich mit OOP-Design oder fehle ich einige Socket-Programmierkonzepte?

Bitte stellen Sie Fragen, wenn Sie etwas nicht verstehen! Schlage vor, wie Dinge im Allgemeinen besser gemacht werden können! Danke!

Antwort

0

Wenn Sie den Eingangs- oder Ausgangsstrom eines Sockels schließen, wird der Socket geschlossen.

Sie sollten keine neue pro Nachricht erstellen, und Sie sollten sie nicht nach dem Senden einer Nachricht schließen. Das gleiche gilt für ObjectInputStream beim Empfang. Verwenden Sie die gleichen für die Lebensdauer der Steckdose.

+0

Wow, habe das überhaupt nicht erwartet! Danke für eine Antwort. :) – GarRudo

+0

Hey. Ich bin auf ein anderes Problem gestoßen, das ich nicht herausfinden kann. Wie kann ich Streams für die Ein-/Ausgabe öffnen? – GarRudo

+0

Ich habe versucht, 2 neue Methoden 'öffentliche void openStreams (Socket-Socket) zu definieren; 'das schafft Instanzen von In/Out für die aktuelle Sitzung und' öffentlichen Socket getSocket(); ' Das gibt Socket einer aktuellen Sitzung in meiner Schnittstelle zurück und implementiert sie. Dann rufe ich Methode nach Verbindungsmethode in der Benutzeroberfläche auf. Aber nichts passiert! Methode, die ein/aus erstellt, kehrt nie zurück und es werden keine Fehler erzeugt! – GarRudo

0

Schließen Sie den Eingang oder den Ausgangsstrom sollte den Sockel schließen. In sendMessage schließen Sie den ObjectOutputStream, der wiederum den zugrunde liegenden Ausgabestream schließt, den Sie an den Konstruktor übergeben haben.

+0

Kein 'sollte' oder 'wahrscheinlich' darüber: das ist genau was passiert. – EJP

Verwandte Themen