介绍:该类起到一个承上启下的作用,维持着TcpServer, Channel, Socket等等之间的练习,后面会通过画图来进行剖析。暂时放下
1.TcpConnection.h文件
///该类对象,客户端和服务器都会用到
///这是一个接口类,所以不用暴露太多细节
class TcpConnection : noncopyable,
public std::enable_shared_from_this<TcpConnection>
{
public:
/// Constructs a TcpConnection with a connected sockfd
///用一个已建立连接成功的sockfd来构造该类对象
/// 用户不应该自己构造。该类对象会在accept()之后调用一个连接回调函数,在其中会构造一个该类对象
///从属的loop,I/O线程池有线程时,则是该loop属于其中一个线程的,如果没有时,则就是主线程的
///loop
TcpConnection(EventLoop* loop,
const string& name, ///连接名称
int sockfd, ///建立连接成功返回的fd
const InetAddress& localAddr, ///本端地址
const InetAddress& peerAddr); ///对端地址
~TcpConnection();
EventLoop* getLoop() const { return loop_; } ///返回从属的loop
const string& name() const { return name_; } ///返回该连接对象的名字
const InetAddress& localAddress() const { return localAddr_; } ///返回本端地址
const InetAddress& peerAddress() const { return peerAddr_; } ///返回对端地址
bool connected() const { return state_ == kConnected; } ///返回连接状态
bool disconnected() const { return state_ == kDisconnected; } ///返回连接状态
// return true if success.
bool getTcpInfo(struct tcp_info*) const;
string getTcpInfoString() const;
///发送数据
// void send(string&& message); // C++11
void send(const void* message, int len);
void send(const StringPiece& message);
// void send(Buffer&& message); // C++11
void send(Buffer* message); // this one will swap data
void shutdown(); // NOT thread safe, no simultaneous calling
// void shutdownAndForceCloseAfter(double seconds); // NOT thread safe, no simultaneous calling
void forceClose(); ///强制关闭连接
void forceCloseWithDelay(double seconds); ///延后强制关闭连接
void setTcpNoDelay(bool on); ///是否开启Nagle算法
// reading or not
void startRead(); ///更新channel监听读事件
void stopRead(); ///更新channel取消监听读事件
bool isReading() const { return reading_; }; // NOT thread safe, may race with start/stopReadInLoop 返回是否在监听读事件
void setContext(const boost::any& context)
{ context_ = context; }
const boost::any& getContext() const
{ return context_; }
boost::any* getMutableContext()
{ return &context_; }
void setConnectionCallback(const ConnectionCallback& cb) ///连接建立成功或者销毁时会执行的回调函数
{ connectionCallback_ = cb; }
void setMessageCallback(const MessageCallback& cb) ///从连接中读取可用的数据后执行的回调函数
{ messageCallback_ = cb; }
void setWriteCompleteCallback(const WriteCompleteCallback& cb) ///写操作完成时执行的回调函数
{ writeCompleteCallback_ = cb; }
///设置高水位
void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)
{ highWaterMarkCallback_ = cb; highWaterMark_ = highWaterMark; }
/// Advanced interface
Buffer* inputBuffer() ///返回读缓存
{ return &inputBuffer_; }
Buffer* outputBuffer() ///返回写缓存
{ return &outputBuffer_; }
/// Internal use only.
void setCloseCallback(const CloseCallback& cb)
{ closeCallback_ = cb; }
// 当TcpServer接收新连接时会调用
void connectEstablished(); // should be called only once
///当TcpServer将该对象从connectmap中移除时,会调用该函数
void connectDestroyed(); // should be called only once
private:
///当前对象状态
enum StateE { kDisconnected, kConnecting, kConnected, kDisconnecting };
void handleRead(Timestamp receiveTime); ///读回调
void handleWrite(); ///写回调
void handleClose(); ///关闭回调
void handleError(); ///错误回调
// void sendInLoop(string&& message);
///发送信息
void sendInLoop(const StringPiece& message);
void sendInLoop(const void* message, size_t len);
///关闭写端
void shutdownInLoop();
// void shutdownAndForceCloseInLoop(double seconds);
///强制关闭连接
void forceCloseInLoop();
///设置当前对象的状态
void setState(StateE s) { state_ = s; }
const char* stateToString() const;
void startReadInLoop(); ///开始监听读事件
void stopReadInLoop(); ///停止监听读事件
EventLoop* loop_; ///从属的loop
const string name_; ///连接名称
StateE state_; // FIXME: use atomic variable
bool reading_; ///是否处于监听读事件
///针对客户端来说,我们不能暴露这些类
///下面我说我fd是,accept()成功时返回的fd,就是建立连接成功时返回的fd
std::unique_ptr<Socket> socket_; ///将建立连接生成的fd封装成Socket对象
std::unique_ptr<Channel> channel_; ///通过loop和fd构造一个Channel对象
const InetAddress localAddr_; ///本端地址
const InetAddress peerAddr_; ///对端地址
ConnectionCallback connectionCallback_; ///初次建立连接成功时或者销毁时的会执行的回调函数
MessageCallback messageCallback_; ///执行完读操作后,将读缓冲区重置
WriteCompleteCallback writeCompleteCallback_; ///写操作完成之后所执行的回调
HighWaterMarkCallback highWaterMarkCallback_;
CloseCallback closeCallback_;
size_t highWaterMark_;
Buffer inputBuffer_;
Buffer outputBuffer_; // FIXME: use list<Buffer> as output buffer.
boost::any context_;
// FIXME: creationTime_, lastReceiveTime_
// bytesReceived_, bytesSent_
};
typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;
2.TcpConnection.cc文件
///会在TcpServer初始化时就设置连接回调函数
void muduo::net::defaultConnectionCallback(const TcpConnectionPtr& conn)
{
LOG_TRACE << conn->localAddress().toIpPort() << " -> "
<< conn->peerAddress().toIpPort() << " is "
<< (conn->connected() ? "UP" : "DOWN");
// do not call conn->forceClose(), because some users want to register message callback only.
}
///会在Tcp初始化时就设置消息读完之后 操作的回调函数
void muduo::net::defaultMessageCallback(const TcpConnectionPtr&,
Buffer* buf,
Timestamp)
{
buf->retrieveAll(); ///将读缓冲区重置,读索引和写索引回到预置位
}
TcpConnection::TcpConnection(EventLoop* loop,
const string& nameArg,
int sockfd,
const InetAddress& localAddr,
const InetAddress& peerAddr)
: loop_(CHECK_NOTNULL(loop)), ///检查loop不为空
name_(nameArg), ///连接名字
state_(kConnecting), ///连接的状态
reading_(true), /// 监听读事件
socket_(new Socket(sockfd)), ///将建立连接成功返回的sockfd进行封装,生成socket_对象
channel_(new Channel(loop, sockfd)), ///生成一个channel对象
localAddr_(localAddr), ///本端地址
peerAddr_(peerAddr), ///对端地址
highWaterMark_(64*1024*1024) ///高水位标记
{
///channel设置读回调,写回调,关闭回调,错误回调
channel_->setReadCallback(
std::bind(&TcpConnection::handleRead, this, _1));
channel_->setWriteCallback(
std::bind(&TcpConnection::handleWrite, this));
channel_->setCloseCallback(
std::bind(&TcpConnection::handleClose, this));
channel_->setErrorCallback(
std::bind(&TcpConnection::handleError, this));
LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this
<< " fd=" << sockfd;
socket_->setKeepAlive(true); ///开启保活机制
}
TcpConnection::~TcpConnection()
{
LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this
<< " fd=" << channel_->fd()
<< " state=" << stateToString();
assert(state_ == kDisconnected); ///断言连接断开状态
}
bool TcpConnection::getTcpInfo(struct tcp_info* tcpi) const
{
return socket_->getTcpInfo(tcpi);
}
string TcpConnection::getTcpInfoString() const
{
char buf[1024];
buf[0] = '\0';
socket_->getTcpInfoString(buf, sizeof buf);
return buf;
}
///发送数据
void TcpConnection::send(const void* data, int len)
{
send(StringPiece(static_cast<const char*>(data), len));
}
void TcpConnection::send(const StringPiece& message)
{
if (state_ == kConnected)
{
if (loop_->isInLoopThread())
{
sendInLoop(message); ///在本线程直接发送数据
}
else
{
void (TcpConnection::*fp)(const StringPiece& message) = &TcpConnection::sendInLoop;
///在loop线程中执行
loop_->runInLoop(
std::bind(fp,
this, // FIXME
message.as_string()));
//std::forward<string>(message)));
}
}
}
// FIXME efficiency!!!
void TcpConnection::send(Buffer* buf)
{
if (state_ == kConnected)
{
if (loop_->isInLoopThread())
{
sendInLoop(buf->peek(), buf->readableBytes());
buf->retrieveAll(); ///将buf缓冲区重置
}
else
{
void (TcpConnection::*fp)(const StringPiece& message) = &TcpConnection::sendInLoop;
loop_->runInLoop(
std::bind(fp,
this, // FIXME
buf->retrieveAllAsString()));
//std::forward<string>(message)));
}
}
}
void TcpConnection::sendInLoop(const StringPiece& message)
{
sendInLoop(message.data(), message.size());
}
///发送数据最后实际调用的函数
void TcpConnection::sendInLoop(const void* data, size_t len)
{
loop_->assertInLoopThread();
ssize_t nwrote = 0;
size_t remaining = len;
bool faultError = false;
if (state_ == kDisconnected)
{
LOG_WARN << "disconnected, give up writing";
return;
}
// if no thing in output queue, try writing directly
if (!channel_->isWriting() && outputBuffer_.readableBytes() == 0)
{
nwrote = sockets::write(channel_->fd(), data, len);
if (nwrote >= 0)
{
remaining = len - nwrote; //剩下未读的字节数量
if (remaining == 0 && writeCompleteCallback_)
{
写完数据后执行的回调任务
loop_->queueInLoop(std::bind(writeCompleteCallback_, shared_from_this()));
}
}
else // nwrote < 0
{
nwrote = 0;
if (errno != EWOULDBLOCK) ///错误不是本应该被阻塞
{
LOG_SYSERR << "TcpConnection::sendInLoop";
if (errno == EPIPE || errno == ECONNRESET) // FIXME: any others?
{
faultError = true; ///默认错误标志置为true
}
}
}
}
assert(remaining <= len);
if (!faultError && remaining > 0)
{
size_t oldLen = outputBuffer_.readableBytes();
if (oldLen + remaining >= highWaterMark_
&& oldLen < highWaterMark_
&& highWaterMarkCallback_)
{
loop_->queueInLoop(std::bind(highWaterMarkCallback_, shared_from_this(), oldLen + remaining));
}
outputBuffer_.append(static_cast<const char*>(data)+nwrote, remaining);
if (!channel_->isWriting())
{
channel_->enableWriting();
}
}
}
void TcpConnection::shutdown()
{
// FIXME: use compare and swap
if (state_ == kConnected)
{
setState(kDisconnecting); ///设置正在取消连接状态
// FIXME: shared_from_this()?
loop_->runInLoop(std::bind(&TcpConnection::shutdownInLoop, this)); ///关闭写端
}
}
///实际上关闭写端
void TcpConnection::shutdownInLoop()
{
loop_->assertInLoopThread();
if (!channel_->isWriting())
{
// we are not writing
socket_->shutdownWrite();
}
}
void TcpConnection::forceClose()
{
// FIXME: use compare and swap
if (state_ == kConnected || state_ == kDisconnecting)
{
setState(kDisconnecting);
loop_->queueInLoop(std::bind(&TcpConnection::forceCloseInLoop, shared_from_this()));
}
}
void TcpConnection::forceCloseWithDelay(double seconds)
{
if (state_ == kConnected || state_ == kDisconnecting)
{
setState(kDisconnecting);
loop_->runAfter(
seconds,
makeWeakCallback(shared_from_this(),
&TcpConnection::forceClose)); // not forceCloseInLoop to avoid race condition
}
}
void TcpConnection::forceCloseInLoop()
{
loop_->assertInLoopThread();
if (state_ == kConnected || state_ == kDisconnecting)
{
// as if we received 0 byte in handleRead();
handleClose();
}
}
const char* TcpConnection::stateToString() const
{
switch (state_)
{
case kDisconnected:
return "kDisconnected";
case kConnecting:
return "kConnecting";
case kConnected:
return "kConnected";
case kDisconnecting:
return "kDisconnecting";
default:
return "unknown state";
}
}
void TcpConnection::setTcpNoDelay(bool on)
{
socket_->setTcpNoDelay(on); ///设置Nagle算法是否开启
}
void TcpConnection::startRead() ///开启监听读事件状态
{
loop_->runInLoop(std::bind(&TcpConnection::startReadInLoop, this));
}
void TcpConnection::startReadInLoop() {
loop_->assertInLoopThread();
if (!reading_ || !channel_->isReading())
{
channel_->enableReading();
reading_ = true;
}
}
void TcpConnection::stopRead() ///取消监听都时间状态
{
loop_->runInLoop(std::bind(&TcpConnection::stopReadInLoop, this));
}
void TcpConnection::stopReadInLoop()
{
loop_->assertInLoopThread();
if (reading_ || channel_->isReading())
{
channel_->disableReading();
reading_ = false;
}
}
void TcpConnection::connectEstablished() ///当新连接被确定时会执行一次
{
loop_->assertInLoopThread();
assert(state_ == kConnecting);
setState(kConnected);
channel_->tie(shared_from_this());
channel_->enableReading();
connectionCallback_(shared_from_this());
}
void TcpConnection::connectDestroyed() ///将该对象从TcpServer中的connectionMap中移除出去
{
loop_->assertInLoopThread();
if (state_ == kConnected)
{
setState(kDisconnected);
channel_->disableAll(); ///取消监听任何事情
connectionCallback_(shared_from_this());
}
channel_->remove();
}
void TcpConnection::handleRead(Timestamp receiveTime) ///channel执行的读回调
{
loop_->assertInLoopThread();
int savedErrno = 0;
ssize_t n = inputBuffer_.readFd(channel_->fd(), &savedErrno); ///从缓冲区中读取数据
if (n > 0)
{
messageCallback_(shared_from_this(), &inputBuffer_, receiveTime);
}
else if (n == 0)
{
handleClose();
}
else
{
errno = savedErrno;
LOG_SYSERR << "TcpConnection::handleRead";
handleError();
}
}
void TcpConnection::handleWrite() ///channel执行的写回调
{
loop_->assertInLoopThread();
if (channel_->isWriting()) ///判断channel是否处于监听写事件
{
ssize_t n = sockets::write(channel_->fd(),
outputBuffer_.peek(),
outputBuffer_.readableBytes());
if (n > 0)
{
outputBuffer_.retrieve(n);
if (outputBuffer_.readableBytes() == 0)
{
channel_->disableWriting(); ///使其不再监听写事件
if (writeCompleteCallback_)
{
loop_->queueInLoop(std::bind(writeCompleteCallback_, shared_from_this()));
}
if (state_ == kDisconnecting)
{
shutdownInLoop(); ///关闭写端
}
}
}
else
{
LOG_SYSERR << "TcpConnection::handleWrite";
// if (state_ == kDisconnecting)
// {
// shutdownInLoop();
// }
}
}
else
{
LOG_TRACE << "Connection fd = " << channel_->fd()
<< " is down, no more writing";
}
}
void TcpConnection::handleClose() ///channel执行的关闭回调
{
loop_->assertInLoopThread();
LOG_TRACE << "fd = " << channel_->fd() << " state = " << stateToString();
assert(state_ == kConnected || state_ == kDisconnecting);
// we don't close fd, leave it to dtor, so we can find leaks easily.
setState(kDisconnected);
channel_->disableAll(); ///channel不监听任何事件
TcpConnectionPtr guardThis(shared_from_this());
connectionCallback_(guardThis);
// must be the last line
closeCallback_(guardThis);
}
void TcpConnection::handleError() ///channel执行的错误回调
{
int err = sockets::getSocketError(channel_->fd());
LOG_ERROR << "TcpConnection::handleError [" << name_
<< "] - SO_ERROR = " << err << " " << strerror_tl(err);
}