java - BufferReader 在连接关闭时仍在运行

标签 java sockets networking

我有一个有点简单的服务器,这意味着我正在尝试通过使服务器尽可能面向对象来学习不同的设计模式。令人惊讶的是,在我创建方法 close() 之前我还没有遇到过一个问题。

很明显,当客户端关闭与数据库的连接时,BufferReader 仍然需要输入并抛出一个 execption 说 Java.net.socketExecption: socket closed

因为我有很多不同的类(class),所以我只会发布目前失败的类(class),如果您需要更多信息,请随时给我发评论。此外,由于我正在尝试从该项目中学习,如果您愿意,请对我的代码发表评论 :)

代码(我所有的代码)

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

    }


}

服务器监听器

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

}

** 聊天人**

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

这没有用,仍然给了我同样的异常(exception)。

最佳答案

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。失去外环。

关于java - BufferReader 在连接关闭时仍在运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13409213/

相关文章:

javascript - Node.js 无法处理多个 tcp 消息

c# - 如何确定 HTTP 响应是否完整

networking - TCP 窗口更新方案

linux - debian:无法连接到网络,也许我的电脑中有 dhcp 服务器

linux - Linux OS中的TCP close()vs shutdown()

java - 将第 3 方 jar 包含在 Maven 阴影 jar 中,而不将其添加到本地存储库

java - 以编程方式检测 BlackBerry 设备及其 PIN

Java应用程序代码结构

javascript - 使用Java在表单Load上加载select html中的查询结果

java - 公共(public)ip套接字网络