Ошибка записи в сокет Java более одного раза - PullRequest
1 голос
/ 17 ноября 2011

В моем приложении Java я использую 2 сетевых подключения к веб-серверу. Я запрашиваю диапазон данных для файла с каждого интерфейса с сообщением GET, и когда я получаю данные, я вычисляю, сколько времени это заняло, и бит / с для каждой ссылки.

Эта часть отлично работает.

(я еще не закрыл розетки)

Я определяю, какая ссылка быстрее, чем «пытается» отправить другой HTTP-запрос GET для остальной части файла по более быстрой ссылке. Вот где моя проблема: 2-й cOut.write (GET) ничего не отправляет, и поэтому я не получаю данных обратно.

Должен ли я закрыть сокет и восстановить соединение, прежде чем я смогу снова в него записать?

редактировать

ОК, чтобы ответить на некоторые вопросы: Да, TCP

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

GET /test-downloads/10mb.txt HTTP/1.1
HOST: www.cse.usf.edu
Range: bytes=0-999999
Connection: Close

Соединение: Закрыть, что делает? например, когда я использую Keep-Alive, я получаю задержку в 5 секунд и все равно не отправляю / не получаю данные при последующей записи / чтении.

// This try block has another fo rthe other link but uses [1]
try {
  skSocket[0] = new Socket( ipServer, 80, InetAddress.getByName(ipLowLink), 0 );
  skSocket[0].setTcpNoDelay(true);
  skSocket[0].setKeepAlive(true);
  cOut[0] = new PrintWriter(skSocket[0].getOutputStream(),true);
  cIn[0] = new InputStreamReader(skSocket[0].getInputStream());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    /* -----------------------------------
       the following code is what is called 
       once for each link (ie cOut[0], cOut [1])
       then after determining which has the better bps
       (using a GET to grab the rest of the file)
       this code is repeated on the designated link
       ----------------------------------- */

    // Make GET header
    GET.append(o.strGetRange(ipServer, File, startRange, endRange-1));
    // send GET for a specific range of data
    cOut[0].print(GET);
    cOut[0].flush();

    try {

        char[] buffer = new char[4*1024];
        int n = 0;
        while (n >= 0) {
            try {
                n = cIn[0].read(buffer, 0, buffer.length);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (n > 0) {
                raw[0].append(buffer, 0, n); // raw is a stringBuffer
            }
        }
    }
    finally {
        //if (b != null) b.close();

}

Я использую тот же код, что и выше, для моей 2-й ссылки (просто смещая диапазон начала / конца по блоку), и после определения бит / с я запрашиваю оставшиеся данные по лучшей ссылке (не беспокойтесь о том, насколько большой файл и т. д., у меня есть вся логика, а не проблема)

Теперь для моего последующего запроса остальных данных я использую тот же код, что и выше, за исключением создания сокета / входа / выхода. Но запись ничего не отправляет. (Я сделал проверку сокетов isClosed (), isConnected (), isBound (), isInputShutdown (), isOutboundShutdown ()), и все доказывают, что сокет все еще открыт / пригоден для использования.

1 Ответ

3 голосов
/ 17 ноября 2011

Согласно спецификации HTTP 1.1, раздел 8 :

An HTTP/1.1 client MAY expect a connection to remain open, but would decide to keep it open based on whether the response from a server contains a Connection header with the connection-token close. In case the client does not want to maintain a connection for more than that request, it SHOULD send a Connection header including the connection-token close.

  1. Итак, вы должны убедиться, что вы используете HTTP1.1, и если вы, вы также должны убедиться, что ваш веб-сервер поддерживает постоянные соединения (вероятно, это так).Однако имейте в виду, что в спецификации указано SHOULD, а не MUST, и поэтому эту функцию можно считать необязательной для некоторых серверов.

  2. Согласно приведенной выше выдержке, проверьте наличиезаголовок соединения с маркером закрытия соединения.

Без SSCCE будет сложно дать какие-либо конкретные рекомендации.

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