连接关闭时,BufferReader仍在运行

时间:2012-11-16 01:44:54

标签: java sockets networking

我有一个简单的服务器意味着我试图通过使服务器尽可能面向对象来学习不同的设计模式。令人惊讶的是,到目前为止,我一直有一个问题,直到我创建方法close()。

当客户端关闭与数据库的连接时,缓冲区仍然需要输入并抛出一个表示Java.net.socketExecption:socket closed

的execption

由于我有很多不同的课程,如果您需要其他信息,我只会发布当前失败的课程,请不要犹豫,发给我评论。此外,因为我正在尝试从这个项目中学习,请评论我的代码以及你是否愿意:)

代码(我的所有代码)

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);

这不起作用仍然给了我相同的效果。

2 个答案:

答案 0 :(得分:2)

Socket上的文档说

  

此套接字上的I / O操作中当前阻塞的任何线程都将抛出SocketException。

您可能想要跳出readline()循环并关闭此外的连接。

答案 1 :(得分: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();
            }
        }
    }

这两个循环都没有意义。一旦达到EOS,readLine()将返回null,此时您应该关闭套接字并退出循环。在任何情况下,isConnected()都不会告诉您关于连接状态的任何信息,只会告诉您在Socket上调用的哪个API是哪个API。失去外圈。