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

 

上次说到函数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;

# 008     c ->Run(rv);

#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的实现。这里既然把消息通过管道发送出去了,那么在另一个线程里肯定就处理的这个消息,下一次再来分析那部份代码。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值