Почему recv () возвращает 0 байтов на всех итерациях цикла for, кроме первой? - PullRequest
2 голосов
/ 29 мая 2011

Я пишу небольшую сетевую программу на C ++. Среди прочего, он должен загрузить изображения профиля в Twitter У меня есть список (stl :: vector) URL-адресов. И я думаю, что моим следующим шагом будет создание цикла for и отправка GET-сообщений через сокет и сохранение изображений в разные png-файлы. Проблема в том, что когда я отправляю самое первое сообщение, получаю ответные сегменты и сохраняю png-данные, все кажется нормальным. Но прямо на следующей итерации то же сообщение, отправленное через тот же сокет, выдает 0 полученных байтов функцией recv (). Я решил проблему, добавив код создания сокета в тело цикла, но я немного запутался с концепциями сокетов. Похоже, что когда я отправляю сообщение, сокет должен быть закрыт и заново создан для отправки следующего сообщения на тот же сервер (чтобы получить следующее изображение). Это правильный способ сетевого программирования сокетов или возможно получить несколько HTTP-сообщений с ответами через один сокет?

Заранее спасибо.

UPD: вот код с циклом, в котором я создаю сокет.

    // Get links from xml.
    ...
    // Load images in cycle.
    int i=0;
    for (i=0; i<imageLinks.size(); i++)
    {
        // New socket is returned from serverConnect. Why do we need to create new at each iteration?
        string srvAddr = "207.123.60.126";
        int socketImg = serverConnect(srvAddr);
        // Create a message.
        ...
        string message = "GET " + relativePart;
                message += " HTTP/1.1\r\n";
        message += "Host: " + hostPart + "\r\n";
        message += "\r\n";
        // Send a message.
        BufferArray tempImgBuffer = sendMessage(sockImg, message, false);
        fstream pFile;
        string name;
        // Form the name.
        ...
        pFile.open(name.c_str(), ios::app | ios::out | ios::in | ios::binary);
        // Write the file contents.
        ...
        pFile.close();
        // Close the socket.
        close(sockImg);
    }

Ответы [ 2 ]

6 голосов
/ 29 мая 2011

Другая сторона закрывает соединение.Вот как HTTP/1.0 работает.Вы можете:

  • Установить разные подключения для каждого HTTP GET
  • Использовать HTTP/1.0 с неофициальным Connection: Keep-Alive
  • Использовать HTTP/1.1HTTP 1.1 все соединения считаются постоянными, если не указано иное.

Обязательная ссылка xkcd Диапазон внимания сервера

Wiki HTTP

Первоначальная версия HTTP (HTTP / 1.0) была пересмотрена в HTTP / 1.1.HTTP / 1.0 использует отдельное соединение с одним и тем же сервером для каждой транзакции запрос-ответ, в то время как HTTP / 1.1 может повторно использовать соединение несколько раз

3 голосов
/ 29 мая 2011

HTTP в своем первоначальном виде (HTTP 1.0) действительно является протоколом «один запрос на соединение». Как только вы получите ответ, другая сторона, вероятно, закрыла соединение. В некоторые реализации были добавлены неофициальные механизмы для поддержки нескольких запросов на соединение, но они не были стандартизированы.

HTTP 1.1 переворачивает это . Все соединения по умолчанию "постоянные".

Чтобы использовать это, вам нужно добавить «HTTP / 1.1» в конец строки запроса. Вместо GET <a href="http://someurl/" rel="nofollow">http://someurl/</a> сделайте GET <a href="http://someurl/" rel="nofollow">http://someurl/</a> HTTP/1.1. При этом вам также нужно будет указать заголовок «Host:».

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

См. Также HTTP 1.1 RFC .

...