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!
Wow, habe das überhaupt nicht erwartet! Danke für eine Antwort. :) – GarRudo
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
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