上次说到函数
WinHttpReadData
接收数据到缓冲区里,那么这些数据又是怎么样传送给下一步处理的呢?带着这个问题,我们来分析下面这段代码,如下:
#001
void HttpTransactionWinHttp::HandleStatusCallback(DWORD status,
#002
DWORD_PTR result,
#003
DWORD error,
#004
DWORD secure_failure) {
#005
int rv = ERR_FAILED;
#006
#007
switch (status) {
#008
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
#009
rv = DidReceiveError(error, secure_failure);
#010
break;
......
#027
#028
if (rv == ERR_IO_PENDING) {
#029
session_callback_->AddRef();
// balanced when callback runs.
#030
} else if (callback_) {
#031
DoCallback(rv);
#032
}
#033
}
通过上面的函数可以看到,当数据接收完成后,就会调用
DoCallback
函数处理接收到的数据。
DoCallback
函数的代码如下:
#001
void HttpTransactionWinHttp::DoCallback(int rv) {
#002
DCHECK(rv != ERR_IO_PENDING);
#003
DCHECK(callback_);
#004
#005
// since Run may result in Read being called, clear callback_ up front.
#006
CompletionCallback* c = callback_;
#007
callback_ = NULL;
#
#009
}
看到这里又是一个回调函数
c->Run
的通知,它是调用开始创建这个连接时设置的回调对象。如果是
HTTP
请求,那么这个请求回调函数是对象
URLRequestHttpJob
里的函数,也就是调用
URLRequestHttpJob::OnReadCompleted
函数,这个函数是当数据接收完成,或接收失败,或者接收还没有完成时都会调用。这个函数代码如下:
#001
void URLRequestHttpJob::OnReadCompleted(int result) {
#002
read_in_progress_ = false;
#003
这里是接收数据完成。
#004
if (result == 0) {
#005
NotifyDone(URLRequestStatus());
#006
} else if (result < 0) {
这里是接收数据出错划。
#007
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
#008
} else {
这里是接收数据还没有完成。
#009
// Clear the IO_PENDING status
#010
SetStatus(URLRequestStatus());
#011
}
#012
#013
NotifyReadComplete(result);
#014
}
当上面读取数据完成时,就开始把接收到数据通过类
ResourceDispatcherHost
来发送出去,而类
ResourceDispatcherHost
发送数据的方式比较特别,它不是通过消息把整块数据用命名管道发送的,而是通过共享内存的方式让另一个进程来读取数据,这样达到速度快的特点,可见可多米处理处理考虑的都是速度,它的代码如下:
#001
bool OnReadCompleted(int request_id, int* bytes_read) {
#002
if (!*bytes_read)
#003
return true;
#004
DCHECK(read_buffer_.get());
#005
#006
if (!rdh_->WillSendData(render_process_host_id_, request_id)) {
#007
// We should not send this data now, we have too many pending requests.
#008
return true;
#009
}
#010
这里创建共享内存。
#011
SharedMemoryHandle handle;
#012
if (!read_buffer_->GiveToProcess(render_process_, &handle)) {
#013
// We wrongfully incremented the pending data count. Fake an ACK message
#014
// to fix this. We can't move this call above the WillSendData because
#015
// it's killing our read_buffer_, and we don't want that when we pause
#016
// the request.
#017
rdh_->OnDataReceivedACK(render_process_host_id_, request_id);
#018
return false;
#019
}
#020
把共享内存通过管道消息发送给渲染进程。
#021
receiver_->Send(new ViewMsg_Resource_DataReceived(
#022
routing_id_, request_id, handle, *bytes_read));
#023
#024
return true;
#025
}
#026
共享内存是使用
Windows API
函数
CreateFileMapping
来创建内存共享文件实现的,具体实现方法请参考类
SharedMemory
的实现。这里既然把消息通过管道发送出去了,那么在另一个线程里肯定就处理的这个消息,下一次再来分析那部份代码。