Connector 主要用于发起连接,并带有自动重连的功能,成员主要有一个channel_,
C++ Code
1
|
boost::scoped_ptr<Channel> channel_;
// Connector所对应的Channel
|
与Acceptor 相比少了一个
acceptSocket_ 成员,因为Connector 是创建一个新的sockfd 并connect 它,如下:Connector::start()-->Connector::startInLoop()-->void Connector::connect()
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void Connector::connect()
{ int sockfd = sockets::createNonblockingOrDie(); // 创建非阻塞套接字 int ret = sockets::connect(sockfd, serverAddr_.getSockAddrInet()); int savedErrno = (ret == 0) ? 0 : errno; switch (savedErrno) { case 0: case EINPROGRESS: // 非阻塞套接字,未连接成功返回码是EINPROGRESS表示正在连接 case EINTR: case EISCONN: // 连接成功 connecting(sockfd); break; .... } } |
-->Connector::connecting()
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void Connector::connecting(
int sockfd)
{ setState(kConnecting); assert(!channel_); // Channel与sockfd关联 channel_.reset( new Channel(loop_, sockfd)); // 设置可写回调函数,这时候如果socket没有错误,sockfd就处于可写状态 channel_->setWriteCallback( boost::bind(&Connector::handleWrite, this)); // FIXME: unsafe // 设置错误回调函数 channel_->setErrorCallback( boost::bind(&Connector::handleError, this)); // FIXME: unsafe channel_->enableWriting(); // 让Poller关注可写事件 } |
现在connnect(sockfd) 没有出错,sockfd 就处于可写状态(内核缓冲区不为满),而且poller 关注了可写事件,触发调用Connector::handleWrite()
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void Connector::handleWrite()
{ LOG_TRACE << "Connector::handleWrite " << state_; if (state_ == kConnecting) { int sockfd = removeAndResetChannel(); // 从poller中移除关注,并将channel置空 // socket可写并不意味着连接一定建立成功 // 还需要用getsockopt(sockfd, SOL_SOCKET, SO_ERROR, ...)再次确认一下。 int err = sockets::getSocketError(sockfd); ...... else // 连接成功 { setState(kConnected); if (connect_) { newConnectionCallback_(sockfd); // 回调 } } } } |
注