Может ли сервер знать, что поток TCP "завершен" независимо от протокола? - PullRequest
2 голосов
/ 21 ноября 2011

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

Редактировать: подумать о созданиипрокси-сервер.Вы не можете влиять на протоколы, вы не знаете аппликативных деталей каждого протокола (поэтому вы не знаете, когда поток «заканчивается»).Относительно "клиент может закрыть входной поток" - это правда, но, очевидно, клиенты фактически не закрывают поток (имеет отношение к повторному использованию?).Это эмпирически проверено с веб-браузерами.

Возможно, я лаю не на то дерево - для этого сценария прокси-сервера не будет достаточно копирования потока в выходной поток «другого конца»?Однако как другой конец «узнает», что поток закончился?

См. Эту программу:

public class Test {
public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8081, 100, InetAddress.getByName("localhost"));
    final Socket socket1 = new Socket("www.google.com", 80);
    final Socket socket = serverSocket.accept();
    new Thread(new Runnable() {
        public void run() {
            try {
                final InputStream inputStream = socket1.getInputStream();
                final OutputStream outputStream = socket.getOutputStream();
                readwrite(inputStream, outputStream, false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    final InputStream inputStream = socket.getInputStream();
    final OutputStream outputStream1 = socket1.getOutputStream();
    readwrite(inputStream, outputStream1, true);

}

private static void readwrite(InputStream inputStream, OutputStream outputStream1, boolean x) throws IOException {
    final byte[] bytes = new byte[4];
    int read = -1;
    while ((read = inputStream.read(bytes)) != -1) {
        System.out.println((x?"s ":"r ") + new String(bytes));
        outputStream1.write(bytes, 0, read);
    }
}
}

Вместо того, чтобы делать то, что, как вы думаете, будет (прокси для www.google.com) просто зависает.Поток, который должен читать из Google и записывать в локальный сокет, не обнаруживает ничего в этом входном потоке.

Edit2: DOH!поставь меня в тупой уголЗабыл "начать" тему.Возвращаясь к моему первоначальному вопросу - как я узнаю, что поток закончился?

Edit3: Ну, моя проблема была совсем другой (касался POST, Transfer-Encoding и HttpClient-annoying-internal-cache-что-мо-быть выключенным).Справедливости ради, я приму ответ, который лучше всего отвечает на исходный вопрос.

Ответы [ 3 ]

1 голос
/ 21 ноября 2011

Если «готово» означает, что входящий или исходящий поток TCP закрыт (так называемое половинное закрытое соединение), то это возможно. Входящий поток закрывается, если inputStream.read(bytes) возвращает -1.

Если «готово» означает что-то еще, то ответ - нет.

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

Не пытайтесь определить, когда доставленный протокол имеет границу сообщения, потому что некоторые протоколы могут постоянно передавать данные в обоих направлениях.

0 голосов
/ 21 ноября 2011

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

0 голосов
/ 21 ноября 2011

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

...