Закрытие сокета

 
 
 
Сообщения:1
Изучаю работу сокетов на примере просто чата
Когда я пытаюсь дисконнектнуть пользователя в окошке сервера при вызове метода disconnect(), у меня подскакивает использование cpu до 95%, а ram на 2гб. Причём это происходит когда метод доходит до одной из трёх строк
out.close();

in.close();

socket.close();

И не важно в каком порядке они стоят, результат - повышенная затрата ресурсов
Плюс окошко пользователя заполняется текстом "null". Не представляю, что может быть причиной
public interface TCPConnectionListener {

    void onConnectionReady(TCPConnection tcpConnection);

    void onRecieveString(TCPConnection tcpConnection, String value);

    void onDisctonnect(TCPConnection tcpConnection);

    void onException(TCPConnection tcpConnection, Exception e);

}


public class TCPConnection {

    private final Socket socket;
    private final Thread thread;
    private final TCPConnectionListener eventListner;
    private final BufferedReader in;
    private final BufferedWriter out;

    public TCPConnection(TCPConnectionListener eventListner, String ipAdress, int port) throws IOException {
        this(eventListner, new Socket(ipAdress, port));
    }

    public TCPConnection(TCPConnectionListener eventListner, Socket socket) throws IOException {
        this.eventListner = eventListner;
        this.socket = socket;
        in = new BufferedReader(new InputStreamReader(socket.getInputStream(), Charset.forName("UTF-8")));
        out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), Charset.forName("UTF-8")));
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    eventListner.onConnectionReady(TCPConnection.this);
                    while (!thread.isInterrupted()) {
                        eventListner.onRecieveString(TCPConnection.this, in.readLine());
                    }
                } catch (IOException ex) {
                    eventListner.onException(TCPConnection.this, ex);
                } finally {
                    eventListner.onDisctonnect(TCPConnection.this);
                }
            }
        });
        thread.start();
    }

    public synchronized void sendString(String value) {
        try {
            out.write(value + "\r\n");
            out.flush();
        } catch (IOException ex) {
            eventListner.onException(TCPConnection.this, ex);
            disconnect();
        }
    }

    public synchronized void disconnect() {
        thread.interrupt();
        try {
            out.close();
            in.close();
            socket.close();
        } catch (IOException ex) {
            eventListner.onException(TCPConnection.this, ex);
        }
    }

    @Override
    public String toString() {
        return "TCPConnection: " + socket.getInetAddress() + ": " + socket.getPort();
    }

}

public class ChatServer implements TCPConnectionListener {

    private final ArrayList<TCPConnection> connections = new ArrayList<>();

    private static ChatServerWindow csw;
    private static ChatServer cs;

    public static ChatServer getCs() {
        return cs;
    }

    public ArrayList<TCPConnection> getConnections() {
        return connections;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                csw = new ChatServerWindow();
            }
        });
        new ChatServer();
    }

    private ChatServer() {
        cs = this;
        try (ServerSocket serverSocket = new ServerSocket(8189)) {
            while (true) {
                try {
                    new TCPConnection(this, serverSocket.accept());
                } catch (IOException e) {
                    System.out.println("TCPConnection exception" + e);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public synchronized void onConnectionReady(TCPConnection tcpConnection) {
        connections.add(tcpConnection);
        csw.getModel().addElement(tcpConnection);
        sendToAllConnections("Client connected: " + tcpConnection);
        csw.printMessage("Client connected: " + tcpConnection);
    }

    @Override
    public synchronized void onRecieveString(TCPConnection tcpConnection, String value) {
        sendToAllConnections(value);
    }

    @Override
    public synchronized void onDisctonnect(TCPConnection tcpConnection) {
        csw.getModel().remove(connections.indexOf(tcpConnection));
        connections.remove(tcpConnection);
        sendToAllConnections("Client disconnected: " + tcpConnection);
        csw.printMessage("Client disconnected: " + tcpConnection);
    }

    @Override
    public synchronized void onException(TCPConnection tcpConnection, Exception e) {
        System.out.println("TCPConnection: " + e);
    }

    private void sendToAllConnections(String value) {
        System.out.println(value);
        final int csize = connections.size();
        for (int i = 0; i < csize; i++) {
            connections.get(i).sendString(value);
        }
    }
}

public class ChatServerWindow extends JFrame implements ActionListener {

    private final int WIDTH = 1200;
    private final int HEIGHT = 400;
    private final JTextArea logs = new JTextArea(20, 40);
    private final JButton kickConnection = new JButton("Удалить соединение");
    private final DefaultListModel model = new DefaultListModel();
    private final JList<String> connections = new JList(model);
    private final JPanel panel = new JPanel();

    protected ChatServerWindow() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(WIDTH, HEIGHT);
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
        logs.setEditable(false);
        logs.setLineWrap(true);
        logs.append("Server running..." + "\n");
        panel.add(new JScrollPane(logs));

        connections.setSize(300, 800);
        panel.add(new JScrollPane(connections));
        kickConnection.addActionListener(this);
        panel.add(kickConnection);
        setContentPane(panel);
        setVisible(true);

    }

    protected synchronized void printMessage(String msg) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                logs.append(msg + "\n");
                logs.setCaretPosition(logs.getDocument().getLength());
            }
        });
    }

    public DefaultListModel getModel() {
        return model;
    }

    @Override
    public void actionPerformed(ActionEvent ae) { 
        final int elementIndex = connections.getSelectedIndex();
        ChatServer.getCs().getConnections().get(elementIndex).disconnect();
    }
    
}

public class ClientWindow extends JFrame implements ActionListener, TCPConnectionListener {

    private final String IP_AdDRESS = "127.0.0.1";
    private final int PORT = 8189;
    private final int WIDTH = 600;
    private final int HEIGHT = 400;
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ClientWindow();
            }
        });
    }
    private final JTextArea log = new JTextArea();
    private final JTextField nickName = new JTextField("Неизвестный пользователь");
    private final JTextField input = new JTextField();

    private TCPConnection connection;
    

    private ClientWindow() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(WIDTH, HEIGHT);
        setLocationRelativeTo(null);
        setAlwaysOnTop(true);
        log.setEditable(false);
        log.setLineWrap(true);
        add(log, BorderLayout.CENTER);

        input.addActionListener(this);
        add(input, BorderLayout.SOUTH);
        add(nickName, BorderLayout.NORTH);
        setVisible(true);
        try {
            connection = new TCPConnection(this, IP_AdDRESS, PORT);
        } catch (IOException ex) {
            printMessage("Connection exception: " + ex);

        }
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        String msg = input.getText();
        if(msg.equals("")) return;
        input.setText(null);
        connection.sendString(nickName.getText()+": "+msg);
    }

    @Override
    public void onConnectionReady(TCPConnection tcpConnection) {
        printMessage("Connection ready...");
    }

    @Override
    public void onRecieveString(TCPConnection tcpConnection, String value) {
        printMessage(value);
    }

    @Override
    public void onDisctonnect(TCPConnection tcpConnection) {
        printMessage("Connection closed");
    }

    @Override
    public void onException(TCPConnection tcpConnection, Exception e) {
        printMessage("Connection exception: " + e);
    }

    private synchronized void printMessage(String msg) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                log.append(msg + "\n");
                log.setCaretPosition(log.getDocument().getLength());
            }
        });
    }

}
Изменен:05 ноя 2018 22:04
 
 
Сообщения:362
я точно не помню..
eventListner.onRecieveString(TCPConnection.this, in.readLine());

посмотри тут как работает in.readLine(), если в поток ничего не пишут:
1. он залипает на этом месте и ждет получения данных
2. при каждом вызове, что-то возвращает

если 1, то в этом и проблема: дисконнект не закрывает/убивает in и.. висяк
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет