1

私はやや単純なサーバーを持っています。つまり、サーバーを可能な限りオブジェクト指向にすることで、さまざまなデザインパターンを学習しようとしています。驚いたことに、これまでのところ、close()メソッドを作成するまで、1つの問題が発生していました。

クライアントがデータベースとの接続を閉じると、BufferReaderはまだ入力を必要とし、次のような実行をスローしJava.net.socketExecptionます:ソケットが閉じられました

私はたくさんの異なるクラスを持っているので、追加情報が必要な場合は、現時点で失敗しているクラスのみを投稿しますので、遠慮なくコメントを送ってください。また、私はこのプロジェクトから学ぼうとしているので、気になったら私のコードにもコメントしてください:)

コード(私のコードすべて)

public class ServerConnectionManager {

    private static ServerSocket server;
    private static Socket connection;
    private static ServerInformation ai = new ServerInformation();
    private static boolean connected = false;
    private static final int portNumber = 7070;
    private static int backLog = 100;

    /**
     * This method launches the server (and the application)!
     * @param args
     */
    public static void main(String[] args){
        startServer();
        waitForConnection();
    }


    /**
     *This method sets the serverSocket to portNumber and also adds the backLog.
     */
    private static void startServer() {
        try {
            server = new ServerSocket(portNumber, backLog);
            connected = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * This method waits for a connection aslong as the serverSocket is connected.
     * When a new client connects it creates an Object of the connection and starts the individual procedure.
     */
    private static void waitForConnection() {
        while (connected) {
            try {
                connection = server.accept();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Connection c = new Connection(connection);
            ai.addToConnectionList(c);
            waitForConnection();
        }

    }


    public void closeMe(Socket con) {
        for (Connection conn : ai.getConnectionList()) {
            if (conn.getConnection() == con) {
                conn.close();
            }
        }
    }



}

繋がり

public class Connection{
    private Socket connection;

    public Connection(Socket connection){
        this.connection = connection;
        ServerListner cl = new ServerListner(Connection.this);
        cl.start();
    }
    public Socket getConnection(){
        return this.connection;
    }
    public void close() {
        try {
            connection.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


}

ServerListner

public class ServerListner extends Thread {

    private Socket connection;
    private BufferedReader br;
    private ChatPerson person;
    private Connection con;
    private ServerInformation ai = new ServerInformation();
    private ServerConnectionManager scm = new ServerConnectionManager();
    private ServerSender sender = new ServerSender();

    public ServerListner(Connection con){
        this.con = con;
        connection = con.getConnection();
        try {
            br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public Socket getConnection(){
        return this.connection;
    }
    public void run(){

        while (con.getConnection().isConnected()) {
            String inString;
            try {
                while ((inString = br.readLine()) != null) {
                    processInput(inString);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public void processInput(String input){
        if (input.equalsIgnoreCase("Connect")) {
            sender.sendMessageToConnection(this.connection, "Accepted");
        }
        if (input.equalsIgnoreCase("UserInformation")) {
            try {
                String username = br.readLine();
                person = new ChatPerson(username, connection);
                ai.add(person);
                System.out.println(ai.getList());

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        if (input.equalsIgnoreCase("SearchByCon")) {
            String name = ai.searchByConnection(connection);
            System.out.println(name);
        }
        if (input.equals("Disconnect")) {
            scm.closeMe(connection);
        }

    }
}

**サーバー送信者**

public class ServerSender {
    private PrintWriter pw;
    private ServerInformation ai = new ServerInformation();

    public void addToList(){

    }
    public void sendToAll(String message){
        for (Connection c : ai.getConnectionList()) {
            try {
                pw = new PrintWriter(c.getConnection().getOutputStream());
                pw.print(message);
                pw.flush();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }
    /** 
     *
     * @param con
     * @param message
     */

    /*
     * Note - Denne metode gør også at jeg kan hviske til folk!:)
     */
    public void sendMessageToConnection(Socket con, String message){
        try {
            PrintWriter print = new PrintWriter(con.getOutputStream());
            print.println(message);
            print.flush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }
}

**サーバー情報**

public class ServerInformation {
    private ArrayList<Connection> connectedClients = new ArrayList<Connection>();
    private ArrayList<ChatPerson> list = new ArrayList<ChatPerson>();


    public ArrayList<Connection> getConnectionList(){
        return connectedClients;
    }
    public void addToConnectionList(Connection con){
        connectedClients.add(con);
    }
    public String searchByConnection(Socket myConnection){
        for (ChatPerson p : list) {
            if (p.getConnection() == myConnection) {
                return p.getName();
            }

        }
        /*
         * If none found!
         */
        return null;
    }

    public void add(ChatPerson p){
        list.add(p);
    }

    public void removeByName(String name){
        for (ChatPerson p : list) {
            if (p.getName().equalsIgnoreCase(name)) {
                list.remove(p);     
            }
        }
    }
    public String searchList(String name){
        for (ChatPerson p : list) {
            if (p.getName().equalsIgnoreCase(name)) {
                return p.getName();
            }
        }
        return null;
    }   
    public ArrayList<ChatPerson>getList(){
        return list;
    }

}

** ChatPerson **

public class ChatPerson {
    private String chatName;
    private Socket connection;

    /*
     * This is for furture development
     * private Integer adminLevel;
     */

    public ChatPerson(String name, Socket connection){
        this.chatName = name;
        this.connection = connection;
    }
    public void setName(String name){
        this.chatName = name;

    }
    public String getName(){
        return chatName;

    }
    public String toString(){
        return "Username: "+chatName;
    }
    public Socket getConnection(){
        return connection;
    }
}

私は次のことを試しました:

try {
            String inString;
            while ((inString = br.readLine()) != null) {
                if (inString.equalsIgnoreCase("Disconnect")) {
                    System.out.println(inString);
                    break;

                }else {
                    processInput(inString);
                }
            }
            scm.closeMe(connection);

これはまだ機能しませんでしたが、私に同じ実行を与えました。

4

2 に答える 2

2

Socketのドキュメントには

このソケットでのI/O操作で現在ブロックされているスレッドは、SocketExceptionをスローします。

readline()ループから抜け出し、これ以外の接続を閉じたい場合があります。

于 2012-11-16T02:06:43.717 に答える
2
while (con.getConnection().isConnected()) {
            String inString;
            try {
                while ((inString = br.readLine()) != null) {
                    processInput(inString);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

これらの両方のループを持つことは無意味です。readLine()EOSに達するとすぐにnullを返します。その時点で、ソケットを閉じてループを終了する必要があります。いずれの場合isConnected()も、接続の状態については何も教えてくれません。接続Socketのエンドポイントである、呼び出したAPIについてのみ教えてくれます。外側のループを失います。

于 2012-11-16T06:47:13.637 に答える