33muduo_net库源码分析(九)
来源:互联网 发布:催收数据安全管理制度 编辑:程序博客网 时间:2024/05/17 02:20
1.TcpServer/TcpConnection
(1)Acceptor类的主要功能是socket、bind、listen
(2)一般来说,在上层应用程序中,我们不直接使用Acceptor,而是把它作为TcpServer的成员TcpServer还包含了一个TcpConnection列表
(3)TcpConnection与Acceptor类似,有两个重要的数据成员,Socket与Channel
2.时序图
3.代码
1.TcpConnection.h
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is a public header file, it must only include public header files.#ifndef MUDUO_NET_TCPCONNECTION_H#define MUDUO_NET_TCPCONNECTION_H#include <muduo/base/Mutex.h>#include <muduo/base/StringPiece.h>#include <muduo/base/Types.h>#include <muduo/net/Callbacks.h>//#include <muduo/net/Buffer.h>#include <muduo/net/InetAddress.h>//#include <boost/any.hpp>#include <boost/enable_shared_from_this.hpp>#include <boost/noncopyable.hpp>#include <boost/scoped_ptr.hpp>#include <boost/shared_ptr.hpp>namespace muduo{namespace net{class Channel;class EventLoop;class Socket;////// TCP connection, for both client and server usage.////// This is an interface class, so don't expose too much details.class TcpConnection : boost::noncopyable, public boost::enable_shared_from_this<TcpConnection>{ public: /// Constructs a TcpConnection with a connected sockfd /// /// User should not create this object. TcpConnection(EventLoop* loop, const string& name, int sockfd, const InetAddress& localAddr, const InetAddress& peerAddr); ~TcpConnection(); EventLoop* getLoop() const { return loop_; } const string& name() const { return name_; } const InetAddress& localAddress() { return localAddr_; } const InetAddress& peerAddress() { return peerAddr_; } bool connected() const { return state_ == kConnected; } void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = cb; } void setMessageCallback(const MessageCallback& cb) { messageCallback_ = cb; } // called when TcpServer accepts a new connection void connectEstablished(); // should be called only once private: enum StateE { /*kDisconnected, */kConnecting, kConnected/*, kDisconnecting*/ }; void handleRead(Timestamp receiveTime); void setState(StateE s) { state_ = s; } EventLoop* loop_;// 所属EventLoop string name_;// 连接名 StateE state_; // FIXME: use atomic variable // we don't expose those classes to client. boost::scoped_ptr<Socket> socket_; boost::scoped_ptr<Channel> channel_; InetAddress localAddr_; InetAddress peerAddr_; ConnectionCallback connectionCallback_; MessageCallback messageCallback_;};typedef boost::shared_ptr<TcpConnection> TcpConnectionPtr;}}#endif // MUDUO_NET_TCPCONNECTION_H
2.TcpConnection.cc
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)#include <muduo/net/TcpConnection.h>#include <muduo/base/Logging.h>#include <muduo/net/Channel.h>#include <muduo/net/EventLoop.h>#include <muduo/net/Socket.h>#include <muduo/net/SocketsOps.h>#include <boost/bind.hpp>#include <errno.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;/*void muduo::net::defaultConnectionCallback(const TcpConnectionPtr& conn){ LOG_TRACE << conn->localAddress().toIpPort() << " -> " << conn->peerAddress().toIpPort() << " is " << (conn->connected() ? "UP" : "DOWN");}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)), name_(nameArg), state_(kConnecting), socket_(new Socket(sockfd)), channel_(new Channel(loop, sockfd)), localAddr_(localAddr), peerAddr_(peerAddr)/*, highWaterMark_(64*1024*1024)*/{ // 通道可读事件到来的时候,回调TcpConnection::handleRead,_1是事件发生时间 channel_->setReadCallback( boost::bind(&TcpConnection::handleRead, this, _1)); LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this << " fd=" << sockfd; socket_->setKeepAlive(true);}TcpConnection::~TcpConnection(){ LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this << " fd=" << channel_->fd();}void TcpConnection::connectEstablished(){ loop_->assertInLoopThread(); assert(state_ == kConnecting); setState(kConnected); channel_->tie(shared_from_this()); channel_->enableReading();// TcpConnection所对应的通道加入到Poller关注 connectionCallback_(shared_from_this());}void TcpConnection::handleRead(Timestamp receiveTime){ /* 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(); } */ loop_->assertInLoopThread(); char buf[65536]; ssize_t n = ::read(channel_->fd(), buf, sizeof buf); messageCallback_(shared_from_this(), buf, n);}
3.TcpServer.h
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is a public header file, it must only include public header files.#ifndef MUDUO_NET_TCPSERVER_H#define MUDUO_NET_TCPSERVER_H#include <muduo/base/Types.h>#include <muduo/net/TcpConnection.h>#include <map>#include <boost/noncopyable.hpp>#include <boost/scoped_ptr.hpp>namespace muduo{namespace net{class Acceptor;class EventLoop;////// TCP server, supports single-threaded and thread-pool models.////// This is an interface class, so don't expose too much details.class TcpServer : boost::noncopyable{ public: //typedef boost::function<void(EventLoop*)> ThreadInitCallback; //TcpServer(EventLoop* loop, const InetAddress& listenAddr); TcpServer(EventLoop* loop, const InetAddress& listenAddr, const string& nameArg); ~TcpServer(); // force out-line dtor, for scoped_ptr members. const string& hostport() const { return hostport_; } const string& name() const { return name_; } /// Starts the server if it's not listenning. /// /// It's harmless to call it multiple times. /// Thread safe. void start(); /// Set connection callback. /// Not thread safe. // 设置连接到来或者连接关闭回调函数 void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = cb; } /// Set message callback. /// Not thread safe. // 设置消息到来回调函数 void setMessageCallback(const MessageCallback& cb) { messageCallback_ = cb; } private: /// Not thread safe, but in loop void newConnection(int sockfd, const InetAddress& peerAddr); typedef std::map<string, TcpConnectionPtr> ConnectionMap; EventLoop* loop_; // the acceptor loop const string hostport_;// 服务端口 const string name_;// 服务名 boost::scoped_ptr<Acceptor> acceptor_; // avoid revealing Acceptor ConnectionCallback connectionCallback_; MessageCallback messageCallback_; bool started_; // always in loop thread int nextConnId_;// 下一个连接ID ConnectionMap connections_;// 连接列表};}}#endif // MUDUO_NET_TCPSERVER_H
4.TcpServer.cc
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)#include <muduo/net/TcpServer.h>#include <muduo/base/Logging.h>#include <muduo/net/Acceptor.h>#include <muduo/net/EventLoop.h>//#include <muduo/net/EventLoopThreadPool.h>#include <muduo/net/SocketsOps.h>#include <boost/bind.hpp>#include <stdio.h> // snprintfusing namespace muduo;using namespace muduo::net;TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr, const string& nameArg) : loop_(CHECK_NOTNULL(loop)), hostport_(listenAddr.toIpPort()), name_(nameArg), acceptor_(new Acceptor(loop, listenAddr)), /*threadPool_(new EventLoopThreadPool(loop)), connectionCallback_(defaultConnectionCallback), messageCallback_(defaultMessageCallback),*/ started_(false), nextConnId_(1){ // Acceptor::handleRead函数中会回调用TcpServer::newConnection // _1对应的是socket文件描述符,_2对应的是对等方的地址(InetAddress) acceptor_->setNewConnectionCallback( boost::bind(&TcpServer::newConnection, this, _1, _2));}TcpServer::~TcpServer(){ loop_->assertInLoopThread(); LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";}// 该函数多次调用是无害的// 该函数可以跨线程调用void TcpServer::start(){ if (!started_) { started_ = true; } if (!acceptor_->listenning()) {// get_pointer返回原生指针 loop_->runInLoop( boost::bind(&Acceptor::listen, get_pointer(acceptor_))); }}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 << "TcpServer::newConnection [" << name_ << "] - new connection [" << connName << "] from " << peerAddr.toIpPort(); InetAddress localAddr(sockets::getLocalAddr(sockfd)); // FIXME poll with zero timeout to double confirm the new connection // FIXME use make_shared if necessary TcpConnectionPtr conn(new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr)); connections_[connName] = conn; conn->setConnectionCallback(connectionCallback_); conn->setMessageCallback(messageCallback_); conn->connectEstablished();}
5.Reactor_test.08.cc
#include <muduo/net/TcpServer.h>#include <muduo/net/EventLoop.h>#include <muduo/net/InetAddress.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;void onConnection(const TcpConnectionPtr& conn){ if (conn->connected()) { printf("onConnection(): new connection [%s] from %s\n", conn->name().c_str(), conn->peerAddress().toIpPort().c_str()); } else { printf("onConnection(): connection [%s] is down\n", conn->name().c_str()); }}void onMessage(const TcpConnectionPtr& conn, const char* data, ssize_t len){ printf("onMessage(): received %zd bytes from connection [%s]\n", len, conn->name().c_str());}int main(){ printf("main(): pid = %d\n", getpid()); InetAddress listenAddr(8888); EventLoop loop; TcpServer server(&loop, listenAddr, "TestServer"); server.setConnectionCallback(onConnection); server.setMessageCallback(onMessage); server.start(); loop.loop();}
阅读全文
0 0
- 33muduo_net库源码分析(九)
- muduo_net库源码分析
- EpollPoller --- muduo_net库源码分析(27)
- 25muduo_net库源码分析(一)
- 26muduo_net库源码分析(二)
- 27muduo_net库源码分析(三)
- 28muduo_net库源码分析(四)
- 29muduo_net库源码分析(五)
- 30muduo_net库源码分析(六)
- 31muduo_net库源码分析(七)
- 32muduo_net库源码分析(八)
- 34muduo_net库源码分析(十)
- muduo_net库源码分析(25)
- muduo_net库源码分析(25)
- muduo_net库源码分析(26-1
- 高并发服务器架构笔记(4)——muduo_net 源码分析
- 18muduo_base库源码分析(九)
- Caffe 源码(九):euclidean_loss_layer 分析
- XListView上拉加载下拉刷新
- 第四章 分治策略
- Fast Input
- CSS实现多栏布局的几种方式
- G
- 33muduo_net库源码分析(九)
- ChokBox的全选反选以及计算数量
- 淡入淡出放大放小
- Lattice Animals UVA
- 关于Unity3D的学习平台
- Android
- 丑数
- 深入解读Quartz的原理
- 实现频道管理