Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java.net.SocketException:Socket是闭合的OOP设计错误_Java_Sockets_Oop - Fatal编程技术网

java.net.SocketException:Socket是闭合的OOP设计错误

java.net.SocketException:Socket是闭合的OOP设计错误,java,sockets,oop,Java,Sockets,Oop,我正在写一个关于银行系统的服务器-客户端通信的大学项目。其中一个要求是应用程序的OOP设计 我在实现通信方法的类中有一个bug 这是一个客户端代码。服务器端的实现类似,并产生相同的错误 错误的结果是java.net.SocketException:Socket已关闭 实现通信方法的类: import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import ja

我正在写一个关于银行系统的服务器-客户端通信的大学项目。其中一个要求是应用程序的OOP设计

我在实现通信方法的类中有一个bug

这是一个客户端代码。服务器端的实现类似,并产生相同的错误

错误的结果是
java.net.SocketException:Socket已关闭

实现通信方法的类:

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
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;
    }
}
这是调用方法并返回调用的方法的标准类返回:

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
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;
    }
}
封装MethodInvoker类和实现通信方法的类之间绑定的类:

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;
    }
}
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);            
    }
}
使用驱动程序对象调用方法的类:

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;
    }
}
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);            
    }
}
我试图缩小代码范围并隔离问题。 类
公共类UserInterface
在运行应用程序的线程的run方法中进一步实例化

我是对OOP设计做得太过分了,还是缺少了一些套接字编程概念

如果你不明白,请提问! 建议如何在总体上做得更好!
谢谢大家!

关闭输入或输出流应关闭套接字。在sendMessage中,关闭ObjectOutputStream,这可能反过来关闭传递到构造函数中的底层输出流。

cls打开套接字的输入或输出流将关闭套接字


您不应该为每条消息创建新的
ObjectOutputStream
,也不应该在发送一条消息后关闭它。接收时,
ObjectInputStream
也是如此。在插座的使用寿命中使用相同的插座。

哇,这一点都没想到!谢谢你的回答。:)嘿我遇到了另一个我想不出来的问题。如何打开流进行输入/输出?我尝试定义了两个新方法“public void openStreams(Socket-Socket);”为当前会话和“publicsocketgetsocket();”创建in/out实例的返回接口中当前会话的套接字并实现它们。然后在用户界面中调用一个接一个的连接方法。但是什么也没发生!创建in/out的方法永远不会返回,也不会产生错误!您必须在两端的
ObjectInputStream
之前创建
ObjectOutputStream
。实际上,您不需要其他方法:只需在创建
套接字的同一位置执行即可。在服务器中,您应该在线程的
run()
方法的头部执行此操作,该线程创建用于处理每个已接受的
Socket
。我现在尝试用不同的方法打开每个流。外流正在开放。在流中打开会冻结程序和方法,永远不会结束。关于它没有“应该”或“可能”:这正是发生的事情。