проблема с tcp сервером и клиентом - PullRequest
0 голосов
/ 19 января 2011

И все, я уже создал несколько программ, связанных с клиентом и сервером.Сегодня это был мой сессионный [практический экзамен] технологии Клиент-сервер.

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

Я пробовал это решение, но было какое-то странное решение: Server.java

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

public class Server{
    public static void main(String args[]) throws Exception{
        ServerSocket s = new ServerSocket(7896);
        Socket cs = s.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(cs.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(cs.getOutputStream()));
        bw.write(br.read() + br.read());
    }
}

Client.java

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

public class Client{
public static void main(String args[]) throws Exception{
    Socket s = new Socket("localhost", 7896);
    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
    bw.write(3);
    bw.write(4);
    System.out.println("Output is: " + br.read());
}
}

когда я запустил его по запросу DOS, у меня появилось два пустых экрана;один на сайте клиента и один на сайте сервера (что было немного удивительно).затем я закрыл сервер, затем внезапно я получил сообщение об ошибке на клиенте, что-то вроде соединения закрыто.

Затем я запустил ту же программу на моем Linux Ubuntu с тем же JDK 1.6, как это было в Windows, и здесь также пустые экраны, но когда язакрытый сервер я получил:

Output is: -1

Хотя на экзамене я сделал это, используя DataOutputStream и DataInputStream.

Но почему вышеприведенный код не работает.

Может ли кто-нибудь объяснить, что там происходит в коде.

Спасибо

Ответы [ 2 ]

3 голосов
/ 19 января 2011

Несколько комментариев, которые могут помочь вам получить правильный ответ:

  • Код сервера в том виде, в каком он есть, может принимать только один запрос клиента, поскольку вызов accept() не выполняется.не присутствует в бесконечном цикле.
  • При использовании буферизованных потоков, убедитесь, что вы всегда очищаете OuputStream/Writer, чтобы гарантировать, что данные фактически записаны вклиент вместо того, чтобы просто лежать в буфере.
  • DataInput / OutputStream абсолютно необходим (или любой другой подход, который логически читает строку «число» и преобразует ее в соответствующее представление, которое может быть добавлено), так как просто чтение из BufferedReader не приводит вас к "цифрам".

Но вопрос в том, зачем нужна промывка?Чтобы ответить на этот вопрос, нужно понять, почему «буферизация» используется в первую очередь.Зачем оборачивать ваши потоки в другой поток, когда вы можете напрямую записывать в свой поток?Причина в том, что операции ввода / вывода стоят действительно дороже (по крайней мере, по сравнению с доступом к вашей памяти или кэш-памяти / регистрам ЦП).Частые записи / чтения при доступе / записи небольших порций данных на жесткий диск могут привести к удушению жесткого диска и снижению общей производительности вашего приложения.

Так в чем же решение?Пишите данные на жесткий диск реже.Это может быть достигнуто двумя способами:

  1. Выделение большого байтового массива вручную и заполнение всего массива за одно чтение.Это намного лучше, чем чтение одного байта.Размер байтового массива требует настройки в соответствии с потребностями вашего приложения, но для общих целей хорошо подойдет 8K.
  2. Используйте буферизованный поток.Это имеет то преимущество, что не подвергает клиентов деталям низкого уровня.Ваше приложение может использовать «поток» по своему усмотрению (непрерывно записывая в него отдельные байты), и поток будет нести полную ответственность за очистку буферизованных данных 1034 *, когда сочтет нужным (это зависит от размера буфера, который вы устанавливаете при создании буферизованного потока).

Хотя объяснение было специфичным для жесткого диска, то же самое относится и к другим типам потока, как в вашем случае сокета.

TL; DR: буферизация улучшает пропускную способность / производительность ввода-вывода.:)

1 голос
/ 19 января 2011

write() будет буферизовать ввод, поэтому нет необходимости делать много мелких записей.Поскольку вы не пишете много в буфер, он, вероятно, все еще там и еще не записан.Вызов flush() заставит его записать буфер.

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