Chrome源代码分析之socket(二)

从这个函数可以看出Chrome采用WSAEventSelect来同服务器端建立连接,虽然WSAEventSelect的在吞吐量和处理多连接的性能这2方面无法与重叠I/O和完成度端口相提并论,但是用在客户端上足矣,而且WSAEventSelect不象WSASyncSelect那样需要与窗口句柄相关联,还能减小网络部分的耦合度,应该说是个不错的选择,不过WSAEventSelect仅仅用于TCP的连接阶段,而发送或者接收数据采用了重叠端口模型,之所以如此,可能是重叠端口只支持Accept,read,write这三个功能,微软更倾向于把重叠端口用于服务器端,connect则缺乏支持。

接着分析write函数:

 

AssertEventNotSignaled(core_->write_overlapped_.hEvent); 

接着重置事件对象为未通知状态

 

 

  int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0,

                   &core_->write_overlapped_, NULL);

  if (rv == 0) {

    if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {

      rv = static_cast<int>(num);

      if (rv > buf_len || rv < 0) {

        LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len

                   << " bytes, but " << rv << " bytes reported.";

        return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;

      }

      static base::StatsCounter write_bytes("tcp.write_bytes");

      write_bytes.Add(rv);

      if (rv > 0)

        use_history_.set_was_used_to_convey_data();

      LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, rv,

                      core_->write_buffer _.buf);

      return rv;

    }

  } else {

    int os_error = WSAGetLastError();

    if (os_error != WSA_IO_PENDING)

      return MapWinsockError(os_error);

  }

 

 

上面这段首先调用WSASend将数据发送出去,接着进行各种错误检查。然后设置回调函数:

 

core_->WatchForWrite();

 

  waiting_write_ = true;

  write_callback_ = callback;

  core_->write_iobuffer_ = buf;

 

 

关于回调的设置的全部细节就在WatchForWrite函数中,而该函数只是调用了write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);

而StartWatching是ObjectWatcher的一个成员函数,我们先分析一下这个ObjectWatcher类,

 

ObjectWatcher的代码在另外一个独立的源文件中,并且被包含在base命名空间中,说明这是一个通用的类。

 

这里首先需简要介绍一下Chrome中线程的实现方式。从实现来说,Chrome的线程模型与很多现场一样,用的是消息循环的手段。每个Chrome干的事情基本上就是在消息循环中等待并执行任务。Chrome又对线程分类,根据线程类别的不同,所起的消息循环有所不同。比如处理进网络I/O的线程用的是MessagePumpForIO类,处理UI的线程用的是MessagePumpForUI类,一般的线程用到的是MessagePumpDefault。不同的消息循环类,主要差异有两个,一是消息循环中需要处理什么样的消息和任务,第二个是循环流程,比如是死循环还是阻塞在某信号量上。一个完整版的Chrome消息循环,包含处理Windows的消息,处理各种Task,处理各个信号量观察者(Watcher),然后阻塞在某个信号量上等待唤醒。一般来说线程循环在处理Watcher的时候只需要检查其信号量,而不需要阻塞在某个I/O上,很好的实现了网络I/O的异步性。

 

ObjectWatcher即是封装了与Watcher相关的数据和操作,本身继承自MessageLoop的成员类DestructionObserver,有2个主要的成员函数,StartWatching开始监视信号量,StopWatching停止监视信号量,DoneWaiting是线程池的回调函数,成员变量主要是watch_,一个Watch结构体。一个私有类Delegate。Watch结构体是ObjectWatcher类的核心,Watch的定义如下:

 

struct ObjectWatcher::Watch : public Task {

  ObjectWatcher* watcher;   

  HANDLE object;             // 被监视的信号量

  HANDLE wait_object;        // RegisterWaitForSingleObject返回的线程池注册句柄

  MessageLoop* origin_loop;  // 所属线程的指针

  Delegate* delegate;        // Delegate 指针

  bool did_signal;           // 执行标识

 

  virtual void Run() {

    //被线程执行函数

    if (!watcher)

      return;

 

    DCHECK(did_signal);

    watcher->StopWatching();

 

    delegate->OnObjectSignaled(object);

  }

};

 

 

这里有必须详细分一下Chrome的线程模型,因此下面2节都用来介绍这个东西。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值