Я не могу закрыть сокет в чате сервера-клиента. Почему? - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть класс MyServer и класс Client, на MyServer у меня есть класс ClientHandler, этот поток, который я создаю, когда новый клиент хочет подключиться к серверу, и два класса ReadThread и WriteThread используются для параллельного чтения и записи.

Если я напишу «quit» на клиенте -> клиент прекратит подключение, но на сервере я все еще могу написать этому клиенту, хотя я вызываю clientSocket.close ().

  1. MyServer:

    package Tools;
    
    import iothreads.ClientHandler;
    import java.io.*;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyServer implements Runnable{
    public final static int PORT = 6666;
    private ServerSocket serverSocket = null;
    private Thread serverThread = null;
    private List<ClientHandler> clients = new ArrayList<>();
    
    public MyServer() {
        try {
            serverSocket = new ServerSocket(PORT);
            System.out.println("I'm waiting on " + InetAddress.getLocalHost().getHostAddress() + "...");
            start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    
    private void start() {
        if(serverThread == null) {
            serverThread = new Thread(this);
            serverThread.start();
        }
    }
    
    public void stop() {
        try {
            if(serverThread != null) {
                serverThread.interrupt();
                serverThread = null;
            }
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    @Override
    public void run()  {
        while (serverThread != null) {
            try {
                addClient(serverSocket.accept());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    private synchronized void addClient(Socket socket) throws IOException {
        ClientHandler clientHandler  = new ClientHandler(socket, this);
        clients.add(clientHandler);
        clientHandler.open();
        clientHandler.start();
    }
    
    
    public synchronized void remove(ClientHandler client) throws IOException {
        System.out.println("Bye");
        clients.remove(client);
    
        try {
            if(client != null) {
                client.close();
                client.interrupt();
                client = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public synchronized void removeAll() {
        clients.forEach(clientHandler -> {
            try {
                clientHandler.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
     }
    }
    
  2. ClientHandler

    package iothreads;
    
    import Tools.MyServer;
    import iothreads.ReadThread;
    import iothreads.WriteThread;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    
    public class ClientHandler extends Thread {
    private Socket clientSocket = null;
    private WriteThread writeThread = null;
    private ReadThread readThread = null;
    private MyServer server = null;
    private PrintWriter out = null;
    private BufferedReader in = null;
    private BufferedReader stdIn = null;
    
    public ClientHandler(Socket clientSocket, MyServer server){
        this.clientSocket = clientSocket;
        this.server = server;
    }
    
    @Override
    public void run() {
        try {
            writeThread = new WriteThread(this);
            readThread = new ReadThread(this);
            writeThread.start();
            readThread.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    
    public Socket getClientSocket() {
        return clientSocket;
    }
    
    public MyServer getServer() {
        return server;
    }
    
    public PrintWriter getOut() {
        return out;
    }
    
    public BufferedReader getIn() {
        return in;
    }
    
    public BufferedReader getStdIn() {
        return stdIn;
    }
    
    public synchronized void open() throws IOException {
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        out = new PrintWriter(clientSocket.getOutputStream(),true);
        stdIn = new BufferedReader(new InputStreamReader(System.in));
    }
    
    public synchronized void close() throws IOException {
        if (clientSocket != null) {
            clientSocket.close();
            clientSocket = null;
        }
    
        if (in != null)  in.close();
        if (out != null) out.close();
        if( stdIn != null) {
            stdIn.close();
        }
    }
    }
    

3.ReadThread:

   package iothreads;

import Tools.MyServer;

import java.io.*;
import java.net.Socket;

public class ReadThread extends Thread{
    private ClientHandler client = null;
    private MyServer server = null;

    public ReadThread(ClientHandler client) throws IOException {
        this.client = client;
        this.server = client.getServer();
    }

    @Override
    public void run() {
        try (
                BufferedReader in = client.getIn();
                Socket clientSocket = client.getClientSocket()
        ) {

            String inputLine;
            while (((inputLine = in.readLine()) != null)) {
                System.out.println("From client -> " + clientSocket.getInetAddress().getHostAddress() + ": " + inputLine);
                if (inputLine.equals("quit")) {
                    server.remove(client);
                    return;
                }
            }
            client.close();
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                    + MyServer.PORT + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }
}

4.WriteThread

package iothreads;

import Tools.MyServer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;


public class WriteThread extends Thread {
    private ClientHandler client = null;
    private Socket clientSocket = null;
    private MyServer server = null;


    public WriteThread(ClientHandler client) throws IOException {
        this.client = client;
        this.clientSocket = client.getClientSocket();
        this.server = client.getServer();
    }

    @Override
    public void run() {

        try (
                PrintWriter out = client.getOut();
                BufferedReader stdIn = client.getStdIn();
                ) {

            String outputLine;
            while ((outputLine = stdIn.readLine()) != null) {
                System.out.println("To client -> " + clientSocket.getInetAddress().getHostAddress());
                out.println(outputLine);
                if (outputLine.equals("quit")){
                    out.println(outputLine);
                    server.stop();
                    server.removeAll();
                    return;
                }
            }
            client.close();
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                    + MyServer.PORT + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }
}

Клиент

package Tools;

import iothreads.ReadThread;
import iothreads.WriteThread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client extends Thread{
private final static String MAIN_SERVER_ADDRESS = "192.168.1.115";
public final static int PORT = 6666;
private PrintWriter out = null;
private BufferedReader in = null;
private BufferedReader stdIn = null;
private Socket clientSocket = null;
private WriteThread writeThread = null;
private ReadThread readThread = null;
private Thread clientThread = null;

public Client() {
    try {
        clientSocket = new Socket(MAIN_SERVER_ADDRESS,PORT);
        startConnection();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


public void open() throws IOException {
    in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    out = new PrintWriter(clientSocket.getOutputStream(),true);
    stdIn = new BufferedReader(new InputStreamReader(System.in));
}

private void startConnection() throws IOException {
    open();
    if(clientThread == null) {
        clientThread = new Thread(this);
        clientThread.start();
    }
}

public void stopConnection() {
    try {
        if(clientThread != null) {
            clientThread.interrupt();
            clientThread = null;
        }
        clientSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    System.out.println("Connected to: " + clientSocket.getLocalAddress().getHostAddress());
    try {
        readThread = new ReadThread(this);
        writeThread = new WriteThread(this);
    } catch (IOException e) {
        e.printStackTrace();
    }
    writeThread.start();
    readThread.start();
}

public void sendMessage() {
    try {
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);
        out.println(clientSocket.getLocalAddress());
    } catch (IOException e) {
        e.printStackTrace();
    }

}

public PrintWriter getOut() {
    return out;
}

public BufferedReader getIn() {
    return in;
}

public BufferedReader getStdIn() {
    return stdIn;
}

public Socket getClientSocket() {
    return clientSocket;
}

}
...