Client¶
Connector¶
对应于TcpServer中的Acceptor,这里是用于客户端向服务端发起连接。由于连接建立后会得到一个sockfd,那么就会一样Channel对象来监听对应的事件。
class Connector : noncopyable,
public std::enable_shared_from_this<Connector>
{
private:
EventLoop* loop_;
std::unique_ptr<Channel> channel_;
}
channel_,当 sockets::connect(...) 成功返回后,那么就会触发channel_的可写事件,调用回调函数handleWrite(),在这个回调函数里,主要是处于安全因素考虑对得到的sockfd进行检测,如果确实是成功个服务端建立了正确连接,那么就调用newConnectionCallback_。此外,还需要在handWrite()中取消对于sockfd可写事件的关注,以防止出现busy-loop。
+ 状态+
kConnected:这个只有在connect建立成功,触发handleWrite时才会具有的状态
+ kConnecting:在handleWrite之前都是这个状态
+ kDisconnected:构造函数初始化即这个状态。在stopInLoop()、restart()、retry()都会将状态重新设置为此状态。
+ 函数
+ stop():是将调用了connect()函数但还没建立好链接,即状态为kConnecting的连接请求停止掉,并关闭sockfd。
+ restart、retry、start():内部都是调用startInLoop(),其内部调用connect()来向服务端发起连接请求。
+ retry()是先关闭sockfd,再调用startInLoop
+ restart()没关闭sockfd,就调用startInLoop
这个里面主要涉及了端口和ip地址复用情况,在`connect()`直接当作建立正确的情况,此时错误 **`EISCONN`**:
```cpp
void Connector::connect() {
int sockfd = sockets::createNonblockingOrDie(serverAddr_.family());
int ret = sockets::connect(sockfd, serverAddr_.getSockAddr());
int savedErrno = (ret == 0) ? 0 : errno;
switch (savedErrno) {
case 0:
case EINPROGRESS: // 由于socket是非堵塞套接字,而connect又不能立即完成的错误。
case EINTR: // 被信号中断
case EISCONN: // 已经连接
connecting(sockfd); // 重新连接
break;
}
...
}
```