Получите blog.domain.com, чтобы появиться как www.domain.com/blog

Вы вызываете recv() в цикле до тех пор, пока сокет не отключится или не сработает (и неправильно записал полученные данные в ваш поток), сохранив все необработанные данные в вашем буфере char*. Это неверный способ чтения HTTP-ответа, особенно если используются HTTP-алименты (в этом случае в конце ответа не произойдет отключение). Вы должны следовать правилам, изложенным в RFC 2616 . А именно:

  1. Прочитать до тех пор, пока не будет встречена последовательность "\r\n\r\n". Пока не читайте байты.
  2. Проанализируйте полученные заголовки согласно правилам в RFC 2616 Раздел 4.4 . Они сообщают вам фактический формат оставшихся данных ответа.
  3. Прочитайте данные в формате, открытом в # 2.
  4. Проверьте полученные заголовки на наличие заголовка Connection: close если ответ использует HTTP 1.1 или отсутствие заголовка Connection: keep-alive, если ответ использует HTTP 0.9 или 1.0. Если обнаружено, закройте конец соединения сокета, потому что сервер закрывает его конец. В противном случае, держите соединение открытым и повторно использовать его для последующих запросов (если вы не сделали это с помощью соединения, и в этом случае его закрыть).
  5. Обработать полученные данные по мере необходимости.

Короче говоря, вам нужно сделать что-то более похожее на это (псевдокод):

string headers[];
byte data[];

string statusLine = read a CRLF-delimited line;
int statusCode = extract from status line;
string responseVersion = extract from status line;

do
{
    string header = read a CRLF-delimited line;
    if (header == "") break;
    add header to headers list;
}
while (true);

if ( !((statusCode in [1xx, 204, 304]) || (request was "HEAD")) )
{
    if (headers["Transfer-Encoding"] ends with "chunked")
    {
        do
        {
            string chunk = read a CRLF delimited line;
            int chunkSize = extract from chunk line;
            if (chunkSize == 0) break;

            read exactly chunkSize number of bytes into data storage;

            read and discard until a CRLF has been read;
        }
        while (true);

        do
        {
            string header = read a CRLF-delimited line;
            if (header == "") break;
            add header to headers list;
        }
        while (true);
    }
    else if (headers["Content-Length"] is present)
    {
        read exactly Content-Length number of bytes into data storage;
    }
    else if (headers["Content-Type"] == "multipart/byteranges")
    {
        string boundary = extract from Content-Type header;
        read into data storage until terminating boundary has been read;
    }
    else
    {
        read bytes into data storage until disconnected;
    }
}

if (!disconnected)
{
    if (responseVersion == "HTTP/1.1")
    {
        if (headers["Connection"] == "close")
            close connection;
    }
    else
    {
        if (headers["Connection"] != "keep-alive")
            close connection;
    }
}

check statusCode for errors;
process data contents, per info in headers list;

1
задан Aglystas 29 September 2010 в 14:45
поделиться