Мой сокет-клиент, кажется, только получает первый ответ от HTTP-сервера. Зачем? - PullRequest
1 голос
/ 04 марта 2012

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

public static void main(String[] args) throws IOException {
    TCPClient client = new TCPClient(new TCPClientObserver());
    client.connect("www.microsoft.com", 80);

    sleep(1000);
    client.send("HTTP GET");

    sleep(5000);
    client.send("XYZ");
}

печать

echo: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
echo: <HTML><HEAD><TITLE>Bad Request</TITLE>
echo: <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
echo: <BODY><h2>Bad Request - Invalid URL</h2>
echo: <hr><p>HTTP Error 400. The request URL is invalid.</p>
echo: </BODY></HTML>

Вот основная логика сокета:

        echoSocket = new Socket("www.microsoft.com", 80);
        out = new PrintWriter(echoSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(
                echoSocket.getInputStream()));

        while (true) {
            String response = in.readLine();
            if (response != null)
                System.out.println("echo: " + response);
        }

Я думаю, проблема заключается в моем цикле?

Полный тестовый код моего приложения можно увидетьздесь: http://codepad.org/bmHwct35

Спасибо

Ответы [ 4 ]

2 голосов
/ 04 марта 2012

Проблема не в цикле, а в первом отправленном вами запросе.«HTTP GET» - неверный запрос, и сервер должен ответить «400 Bad request», а затем закрыть соединение.Вот почему вы не получите ответ на ваше второе сообщение.Попробуйте вместо этого правильный HTTP-запрос, например «GET / HTTP / 1.1 \ r \ nHost: www.microsoft.com \ r \ n \ r \ n»Соединения HTTP 1.1 по умолчанию поддерживаются, поэтому вы сможете отправлять несколько из них и получать последующие ответы.

1 голос
/ 04 марта 2012

Предполагая, что HTTP 400 - это то, что вы ожидали, вам нужно выйти из цикла, если readLine () вернет null.Это обычно пишется так:

while ((line = in.readLine()) != null)
{
    // ...
}
1 голос
/ 04 марта 2012

Первый отправленный вами запрос является недействительным, и после ответа сервер закроет соединение. Затем в вашем коде вы застряли в цикле while (true), так как вы продолжите получать null от readLine, так как соединение / поток закрыты (достигнут конец потока).

while (true) { // <-- never terminates
  String response = in.readLine();
  if (response != null) // <- now null all the time
    System.out.println("echo: " + response);
}
1 голос
/ 04 марта 2012

Проблема в том, что HTTP-серверы обмениваются данными по протоколу HTTP, а ваш клиентский код неправильно передает протокол.Вместо этого он открывает простой сокет и пишет случайные вещи, которые, кажется, основаны на догадках.

Протокол HTTP указан в этого документа .Если вы прочитаете его, вы увидите, что то, что вы делаете, не похоже на то, что должен делать клиент.

Я рекомендую вам не пытаться реализовать ваш клиент таким образом.Реализация клиентской части протокола HTTP с нуля - это слишком много работы ... и миру не нужен еще один ненадежный HTTP-клиент.Либо используйте стандартные API URL / HttpURLConnection, либо используйте стороннюю клиентскую библиотеку HTTP.


В вашем случае ответ 400, скорее всего, является следствием отправки некорректного запроса.Предполагается, что HTTP-запрос GET (на самом деле любой HTTP-запрос) включает целевой URL в первой строке.Прочитайте спецификацию.

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