谷歌浏览器的源码分析(29)

来源:互联网 发布:unity3d寻路插件 编辑:程序博客网 时间:2024/05/01 23:41
 

上一次说到通过WinHTTP来接收网络数据,但没有具体介绍怎么样接收,现在就来分析这方面的代码。首先是通过函数WinHttpQueryHeaders来查询HTTP协议头的大小,接着还是通过函数WinHttpQueryHeaders把数据接收到缓冲区里。下面这段代码,就是做这样的事情:

#001  int HttpTransactionWinHttp::DidReceiveHeaders() {

#002    session_callback_->set_load_state(LOAD_STATE_IDLE);

#003 

 

第一次调用函数WinHttpQueryHeaders查看接收到协议头的大小。

#004    DWORD size = 0;

#005    if (!WinHttpQueryHeaders(request_handle_,

#006                             WINHTTP_QUERY_RAW_HEADERS,

#007                             WINHTTP_HEADER_NAME_BY_INDEX,

#008                             NULL,

#009                             &size,

#010                             WINHTTP_NO_HEADER_INDEX)) {

#011      DWORD error = GetLastError();

#012      if (error != ERROR_INSUFFICIENT_BUFFER) {

#013        DLOG(ERROR) << "WinHttpQueryHeaders failed: " << GetLastError();

#014        return TranslateLastOSError();

#015      }

#016      // OK, size should tell us how much to allocate...

#017      DCHECK(size > 0);

#018    }

#019 

 

第二次调用函数WinHttpQueryHeaders来接收协议头的数据。

#020    std::wstring raw_headers;

#021 

#022    // 'size' is the number of bytes rather than the number of characters.

#023    DCHECK(size % 2 == 0);

#024    if (!WinHttpQueryHeaders(request_handle_,

#025                             WINHTTP_QUERY_RAW_HEADERS,

#026                             WINHTTP_HEADER_NAME_BY_INDEX,

#027                             WriteInto(&raw_headers, size/2 + 1),

#028                             &size,

#029                             WINHTTP_NO_HEADER_INDEX)) {

#030      DLOG(ERROR) << "WinHttpQueryHeaders failed: " << GetLastError();

#031      return TranslateLastOSError();

#032    }

#033 

 

设置回应的一些状态。

#034    response_.response_time = Time::Now();

#035 

#036    // From experimentation, it appears that WinHttp translates non-ASCII bytes

#037    // found in the response headers to UTF-16 assuming that they are encoded

#038    // using the default system charset.  We attempt to undo that here.

#039    response_.headers =

#040        new HttpResponseHeaders(base::SysWideToNativeMB(raw_headers));

#041 

#042    // WinHTTP truncates a response longer than 2GB.  Perhaps it stores the

#043    // response's content length in a signed 32-bit integer.  We fail rather

#044    // than reading a truncated response.

#045    if (response_.headers->GetContentLength() > 0x80000000)

#046      return ERR_FILE_TOO_BIG;

#047 

#048    response_.vary_data.Init(*request_, *response_.headers);

#049    PopulateAuthChallenge();

#050 

#051    // Unfortunately, WinHttp does not close the connection when a non-keepalive

#052    // response is _not_ followed by the server closing the connection.  So, we

#053    // attempt to hack around this bug.

#054    if (!response_.headers->IsKeepAlive())

#055      content_length_remaining_ = response_.headers->GetContentLength();

#056 

#057    return OK;

#058  }

 

通过上面的函数处理,就可以收到HTTP协议头的数据,这样就可以进一步处理了。那么接着下来就是收到HTTP协议里的数据,这个主要通过下面的函数来接收到的,如下:

#001  BOOL HttpTransactionWinHttp::SessionCallback::ReadData(

#002      HINTERNET request_handle) {

#003    DCHECK(bytes_available_ >= 0);

#004    char* buf = read_buf_;

#005    read_buf_ = NULL;

#006    int bytes_to_read = std::min(bytes_available_, read_buf_len_);

#007    read_buf_len_ = 0;

#008    if (!bytes_to_read)

#009      bytes_to_read = 1;

#010 

#011    // Because of how WinHTTP fills memory when used asynchronously, Purify isn't

#012    // able to detect that it's been initialized, so it scans for 0xcd in the

#013    // buffer and reports UMRs (uninitialized memory reads) for those individual

#014    // bytes. We override that to avoid the false error reports.

#015    // See http://b/issue?id=1173916.

#016    base::MemoryDebug::MarkAsInitialized(buf, bytes_to_read);

#017    return WinHttpReadData(request_handle, buf, bytes_to_read, NULL);

#018  }

上面通过判断可以接收到多少字节,然后通过函数WinHttpReadData把数据保存到缓冲区read_buf_里,在这个缓冲区里保存了所有网络接收到的数据,那么这些数据又将要流向何方呢?下一次再来分析这个问题。