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;
}
...
}
```