上次說到函數(shù)
WinHttpReadData
接收數(shù)據(jù)到緩沖區(qū)里,那么這些數(shù)據(jù)又是怎么樣傳送給下一步處理的呢?帶著這個問題,我們來分析下面這段代碼,如下:
#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
?
}
通過上面的函數(shù)可以看到,當數(shù)據(jù)接收完成后,就會調(diào)用
DoCallback
函數(shù)處理接收到的數(shù)據(jù)。
DoCallback
函數(shù)的代碼如下:
#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
?
}
看到這里又是一個回調(diào)函數(shù)
c->Run
的通知,它是調(diào)用開始創(chuàng)建這個連接時設置的回調(diào)對象。如果是
HTTP
請求,那么這個請求回調(diào)函數(shù)是對象
URLRequestHttpJob
里的函數(shù),也就是調(diào)用
URLRequestHttpJob::OnReadCompleted
函數(shù),這個函數(shù)是當數(shù)據(jù)接收完成,或接收失敗,或者接收還沒有完成時都會調(diào)用。這個函數(shù)代碼如下:
#001
?
void URLRequestHttpJob::OnReadCompleted(int result) {
#002
???
read_in_progress_ = false;
#003
?
這里是接收數(shù)據(jù)完成。
#004
???
if (result == 0) {
#005
?????
NotifyDone(URLRequestStatus());
#006
???
} else if (result < 0) {
這里是接收數(shù)據(jù)出錯劃。
#007
?????
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
#008
???
} else {
這里是接收數(shù)據(jù)還沒有完成。
#009
?????
// Clear the IO_PENDING status
#010
?????
SetStatus(URLRequestStatus());
#011
???
}
#012
?
#013
???
NotifyReadComplete(result);
#014
?
}
當上面讀取數(shù)據(jù)完成時,就開始把接收到數(shù)據(jù)通過類
ResourceDispatcherHost
來發(fā)送出去,而類
ResourceDispatcherHost
發(fā)送數(shù)據(jù)的方式比較特別,它不是通過消息把整塊數(shù)據(jù)用命名管道發(fā)送的,而是通過共享內(nèi)存的方式讓另一個進程來讀取數(shù)據(jù),這樣達到速度快的特點,可見可多米處理處理考慮的都是速度,它的代碼如下:
#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
?
這里創(chuàng)建共享內(nèi)存。
#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
?
把共享內(nèi)存通過管道消息發(fā)送給渲染進程。
#021
?????
receiver_->Send(new ViewMsg_Resource_DataReceived(
#022
?????????
routing_id_, request_id, handle, *bytes_read));
#023
?
#024
?????
return true;
#025
???
}
#026
?
共享內(nèi)存是使用
Windows API
函數(shù)
CreateFileMapping
來創(chuàng)建內(nèi)存共享文件實現(xiàn)的,具體實現(xiàn)方法請參考類
SharedMemory
的實現(xiàn)。這里既然把消息通過管道發(fā)送出去了,那么在另一個線程里肯定就處理的這個消息,下一次再來分析那部份代碼。
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
