Никаких исключений не выдается, когда сокет закрыт - PullRequest
1 голос
/ 19 ноября 2011

Когда сокет сервера закрыт, клиент не получает никаких исключений даже после записи в OutputStream и сокет сервера уже close .

Предоставление следующих классов для проверки этого:

public class ModemServerSocket {

    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocket serverSocket = new ServerSocket(63333);
        Socket client = serverSocket.accept();
        BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
        String s;

        while ((s = reader.readLine()) != null) {
            System.out.println(s);
            if (s.equals("q")) {                
                break;
            }
        }

        serverSocket.close();
    }

}

открытый класс ModemClientSocket {

    public static void main(String[] args) throws IOException, InterruptedException {
        Socket socket = new Socket("localhost", 63333);
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);
        String[] sArray = {"hello", "q", "still there?"};
        for (String s : sArray) {
            writer.println(s);
            if (s.equals("q")) {
                Thread.sleep(5 * 1000);
            }
        }
        System.out.println("Whoop. No exception. The client didn't notice.");       
    }

}

Я запустил приложение ModemServerSocket, после чего запустилПриложение ModemClientSocket.

Выход ModemServerSocket :

hello 
q

Выход ModemClientSocket :

Whoop. No exception. The client didn't notice.

Это ожидаемое поведение?Почему это происходит?

Однако я провел еще один тест, в котором я закрываю ModemClientSocket, а ModemServerSocket пытается прочитать из InputStream, в этом случае я получил java.net.SocketException , чтоЯ ожидал.Странно то, что для PrintWriter (OutputStream) ничего не происходит, и исключение не выдается.

Я использовал Java 1.6.0 Update 26 для тестов.

Ответы [ 3 ]

4 голосов
/ 19 ноября 2011

Цитирование документации JDK для PrintWriter ниже.

Методы в этом классе никогда не генерируют исключения ввода-вывода , хотя некоторые из его конструкторов могут. Клиент может узнать, возникли ли какие-либо ошибки, вызвав checkError ().

Документация к PrinterWriter

2 голосов
/ 09 августа 2013

На основании некоторых тестов, которые я провел, даже если вы не используете PrintWriter и вместо этого пишете напрямую в socket.getOutputStream (), я не думаю, что вам гарантировано исключение, когда сервер закрывает свой сокет, но еслиВы вызываете write () достаточно раз, и кажется, что в конечном итоге вы получите исключение.

Обратите внимание, что иногда существует различие в поведении в зависимости от того, находятся ли клиент и сервер на одном компьютере или нет.При локальном запуске, по-видимому, требуется меньше операций записи, прежде чем произойдет исключение «SocketException: Broken pipe».

Если вы хотите реально обнаружить, что сокет закрыт, вам нужно прочитайте из него и проверьте, возвращает ли чтение -1.(и, конечно, обрабатывать любые исключения)

Например:

if (socket.getInputStream().read(bytearray) < 0)
    break;

Если сервер ничего не отправляет, вы можете взломать его, вызвав socket.setSoTimeout (1),и обработку / игнорирование SocketTimeoutException, но «правильный» способ сделать это, вероятно, начать с SocketChannel вместо Socket, чтобы вы могли использовать Selector , который должен уведомлять вас при чтении() метод может быть вызван.

btw, строка serverSocket.close () немного вводит в заблуждение и, вероятно, должна быть client.close ().Однако сразу после этого класс завершается, поэтому все сокеты все равно будут закрыты.

2 голосов
/ 19 ноября 2011

Я считаю, что закрытие ServerSocket просто означает, что никакие новые подключения не будут приняты - он не закрывает соединения, которые уже были установлены (вам нужно вызвать client.close ()в ModemServerSocket, чтобы сделать это).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...