Как отправить ответ с TCP-сервера на TCP-клиент? - PullRequest
0 голосов
/ 05 июня 2018

У меня следующий код для сервера и клиента.Клиент может успешно отправлять данные на сервер, но когда клиент пытается прочитать данные с сервера, код продолжает работать без вывода.

Сервер:

public static void main(String[] args) throws Exception {

    ServerSocket s = new ServerSocket(9898);

    while(true) {

        Socket recv = s.accept();

        InputStream inp = recv.getInputStream();
        OutputStream out = recv.getOutputStream();

        String data = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(inp));
        while ( (data = in.readLine()) != null ) {
            System.out.println("\r" + data);
        }

        out.write("sampleSendToClient".getBytes());
    }

}

Клиент:

public static void main(String[] args) throws Exception{
    Socket clientSocket = new Socket("localhost", 9898);
    OutputStream out = clientSocket.getOutputStream();
    InputStream inp = clientSocket.getInputStream();

    out.write("sampleSendToServer".getBytes());

    String data = null;
    //if I dont write next 4 lines then client exits gracefully 
    //but now it is stuck infinitely
    BufferedReader in = new BufferedReader(new InputStreamReader(inp));
    while ( (data = in.readLine()) != null ) {
        System.out.println("\r" + data);
    }

    clientSocket.close();
}

Я не могу понять, что не так в приведенном выше коде.

1 Ответ

0 голосов
/ 05 июня 2018

Быстро, но безболезненно ваш сервер пишет прямо в выходной поток, вызывая OutputStream#write(byte[] data), но ваши клиенты читают с BufferedReader, а BufferedReader#readLine() - это блокирующая операция ввода / вывода, которая приостановит его потокпока символ \n или \r не прибудет на InputStream (или поток не будет закрыт, в этом случае метод будет прерван, а null будет возвращен).

Строка, которую отправляет ваш сервер, делаетне заканчивается \n или \r, поэтому данные могут быть уже отправлены и задерживаться в буфере клиентского BufferedReader, но без этих завершающих символов readLine() никогда не вернется.

Просто измените

out.write("sampleSendToClient".getBytes());

до

out.write("sampleSendToClient\n".getBytes());

должны сделать трюк.

Обновление:

while ( (data = in.readLine()) != null ) {
        System.out.println(data);
    }

Этот цикл while завершится только еслиreadLine() возвращает null это будет иметь место, только если поток закрыт.Однако, поскольку вы не можете закрыть потоки без потери соединения, вам придется найти другой способ завершить цикл, потому что теперь он будет работать вечно.

Даже после добавления \n ваш сервер не будет отвечатьпотому что он будет бесконечно зацикливаться в этой точке.


С другой стороны: для каждого нового соединения вы перезаписываете предыдущий сокет, не закрывая его ресурсы (в первую очередь ориентированные на поток данных и сами сокеты)и, следовательно, создание утечек ресурсов.Попробуйте закрыть каждый объект, когда он больше не нужен.

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