muduo网络库源码复现笔记(二十二):TcpServer类与TcpConnection初步

Muduo网络库简介

muduo 是一个基于 Reactor 模式的现代 C++ 网络库,作者陈硕。它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。
muduo网络库的核心代码只有数千行,在网络编程技术学习的进阶阶段,muduo是一个非常值得学习的开源库。目前我也是刚刚开始学习这个网络库的源码,希望将这个学习过程记录下来。这个网络库的源码已经发布在GitHub上,可以点击这里阅读。目前Github上这份源码已经被作者用c++11重写,我学习的版本是没有使用c++11版本的。不过二者大同小异,核心思想是没有变化的。点这里可以看我的源代码。从笔记十七开始记录muduo的net库的实现过程。如果你需要看一下基础库(base)的复现过程,可以点击这里:muduo的base库实现过程。而网络库的笔记在这里:
muduo网络库源码复现笔记(十七):什么都不做的EventLoop
muduo网络库源码复现笔记(十八):Reactor的关键结构
muduo网络库源码复现笔记(十九):TimeQueue定时器
muduo网络库源码复现笔记(二十):EventLoop::runInloop()函数和EventLoopThread类
muduo网络库源码复现笔记(二十一):Acceptor类、InetAddress类、Sockets类、SocketsOps.cc

1 TcpServer类

前面我们讲了Acceptor类,我们也说过这个类用于监听网络连接。实际上用户将不会直接使用这个类,这个类实际上是由TcpServer类来调用的。
TcpServer类的作用是管理由Acceptor获得的网络连接,并建立相应的TcpConnection连接。下面看一下它的代码:

class TcpServer : boost::noncopyable
{
    
    
public:
	//typedef boost::function<void(EventLoop*)> ThreadInitCallback;
	//TcpServer(EventLoop* loop,const InetAddress& listenAddr);
	TcpServer(EventLoop* loop,const InetAddress& lostenAddr,
			  const string& nameArg);
	
	~TcpServer();

	const string& hostport() const {
    
    return hostport_;}
	const string& name() const {
    
    return name_;}
 
	//start the server
	void start();

	void setConnectionCallback(const ConnectionCallback& cb)
	{
    
    	connectionCallback_ = cb;	}

	void setMessageCallback(const MessageCallback& cb)
	{
    
    	messageCallback_ = cb;	}

private:
	void newConnection(int sockfd,const InetAddress& peerAddr);
	
	typedef std::map<string,TcpConnectionPtr> ConnectionMap;
	EventLoop* loop_;
	const string hostport_;
	const string name_;
	boost::scoped_ptr<Acceptor> acceptor_;
	ConnectionCallback connectionCallback_;
	MessageCallback messageCallback_;
	bool started_;
	// in loop thread
	int nextConnId_;
	ConnectionMap connections_;
};

TcpServer通过ConnectionMap掌管连接,map的key是连接名称,value是TcpConnection类的指针。
其中最值得注意的是newConnection函数,这个函数将在TcpServer被创立的时候绑定给acceptor_,若acceptor监听到新的网络连接,newConnection将会被调用。newConnection会创建一个TcpConnection,将其指针加入map,设置相应的connectionCallback和messageCallback。代码如下:

void TcpServer::newConnection(int sockfd,const InetAddress& peerAddr)
{
    
    
	loop_ -> assertInLoopThread();
	char buf[32];
	snprintf(buf,sizeof buf,":%s#%d",hostport_.c_str(),nextConnId_);
	++nextConnId_;
	string connName = name_ + buf;

	LOG_INFO << "TcpServerLLnewConnection [" << name_
			 << "] - new connection [" << connName
			 << "] from " << peerAddr.toIpPort();

	InetAddress localAddr(sockets::getLocalAddr(sockfd));
	
	TcpConnectionPtr conn(new TcpConnection(loop_,
											connName,
											sockfd,
											localAddr,
											peerAddr));
	connections_[connName] = conn;
	conn -> setConnectionCallback(connectionCallback_);
	conn -> setMessageCallback(messageCallback_);

	conn -> connectEstablished();
}

2 TcpConnection类初步

TcpConnection类是muduo最复杂、最核心的类。它的作用如前所述,便是进行一次Tcp连接。这一节的TcpConnection还比较简陋,先初步看看它的成员。

private:
	enum stateE {
    
    /*kDisConnected*/kConnecting,kConnected/*,kDisConnecting*/};
	void handleRead(Timestamp receiveTime);
	void setState(stateE s) {
    
     state_ = s; }	
	
	EventLoop* loop_;
	string name_; //connection name
	stateE state_;
	boost::scoped_ptr<Socket> socket_;
	boost::scoped_ptr<Channel> channel_;
	InetAddress localAddr_;
	InetAddress peerAddr_;
	ConnectionCallback connectionCallback_;
	MessageCallback messageCallback_;

TcpConnection有两个成员很重要,分别是socket_和channel_。socket_是一个Socket类指针,指向的Socket的socket的文件描述符便是与客户端通信的connfd。channel_的作用是,当建立连接时,将connfd与channel_绑定,然后将channel_加入到poller中,方便后续的通信。
connectionCallback_与messageCallback_实际上会由TcpServer设置,分别在建立连接和通信时调用。

猜你喜欢

转载自blog.csdn.net/MoonWisher_liang/article/details/107614786
今日推荐