上一次说到通过
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_
里,在这个缓冲区里保存了所有网络接收到的数据,那么这些数据又将要流向何方呢?下一次再来分析这个问题。