学习muduo(类之间的函数调用,未完成)
来源:互联网 发布:淘宝大学金牌讲师小飞 编辑:程序博客网 时间:2024/06/11 14:46
先随便说一句,muduo里边回调函数很多,很容易让人头大。这大概也是松耦合设计的缺点吧?模块之间的耦合度降低了,设计或者编程的复杂度也上升了。
先从server的角度来看。
用muduo库实现一个echo服务器,并在函数中添加相应的注释以了解函数调用的流程(并在windows上进行改写)。echo是这样的(函数实现略):
#pragma once#include"TcpServer.h"class EchoServer{public: EchoServer(EventLoop* loop, const InetAddress& listenAddr); void start(); // calls server_.start();private: void onConnection(const TcpConnectionPtr& conn); void onMessage(const TcpConnectionPtr& conn, Buffer* buf); TcpServer server_;};
main程序是这样的
#pragma once#include "echo.h"#include"EventLoop.h"#include<iostream>using std::cout; using std::cin; using std::endl;#pragma comment(lib,"ws2_32.lib")int main(){ WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); EventLoop loop; InetAddress listenAddr(7878); EchoServer server(&loop, listenAddr); server.start(); loop.loop();}
1~2:我们定义一个eventloop,它包含一个Poller,Poller类封装了select,poll,epoll或者windows下的WSAPoll。
3~8:定义一个EchoServer,先构造TcpServer,server的话有一个acceptor类,它负责管理 listenSocket和 listenChannel 这两个重要的东西。
9~16: 调用接口start,acceptor调用listen,一方面socket调用listen,另一方面channel更新自己感兴趣的事件(读),poller中的channelMap也得到对应的更新。
17~33:开始loop循环,调用poller中的poll,根据返回值更新 avtiveChannelList,并调用对应的handleEvnet。对于 listenchannel 来说,它的handleEvent就是创建一个新的TcpConnection,而这个新的TcpConnection里边包含一个channel,这个channel是用来c/s通信的。
35~ :之后就是一直loop循环。如果是 listenSocket 可读,就创建新连接并执行对应更新;如果是tcpConnection中的channel或者说socket 有事件,就执行对应的handle。
当连接建立完毕之后,在客户端发送消息,则poll返回时EventLoop可以获得一个activeChannel。对于上边的echo服务器来说,是TcpConnection中的Channel有读事件发生,则调用此Channel的handleRead,也即TcpConnection的handleRead,它将可读的数据用readFd函数存放在Buffer中,并调用echoServer传过来的onMessage函数,即把数据回显给客户端。
再说一说回调函数的走向。
首先关注“三个半事件”,连接的建立、断开、消息到来、发送完毕,即对应的1.connect、2.close、3.onMessage、4.writeComplete(半个事件)。
对于服务器端编程来说,我们需要自己编写1 3 4函数,并注册给TcpServer(也不一定要全部)。TcpServer也毫无保留,全部都注册给了TcpConnection。还剩一个2函数,这个是TcpServer自己编写的,removeConnection 也传给TcpConnection。
同时,在TcpServer中,还有这样两个回调函数,newConnection、removeConnection。
1. 前者newConnection被注册给acceptor,acceptor再将它包装注册给它的channel,那么现在创建tcpConnection的权力就交给了listenChannel,就像上边函数流程中的,当listenChannel的套接字在EventLoop中poll返回而检测到可读时,它就行使自己创建tcpConnection的权力。还没完,TcpConnection构建时做的三件事就是,1.增加tcpServer中指向自己的指针、2允许channel中事件可读、3增加poller中指向channel的指针。
2. 后者removeConnection则被直接注册到TcpConnection中的handleClose,这样连接关闭时就回调removeConnection,一方面要删除tcpServer中 连接表 中的连接,一方面还要调用TcpConnection中的connectDestroyed(它是用来关闭channel关注的事件,并删除poller指向channel的指针)。为什么要这样相互回调?是因为他们之间的关系,想一想TcpConnection和谁有关系,再想一想销毁一个TcpConnection需要更新哪些对应的地方。首先它里边有个channel,有一个poller对象指向它(并且poller里边的pollfd依赖于它),所以销毁TcpConnection需要销毁channel,就要先通知poller做出改变。所以,以TcpConnection销毁时做的三件事就是,1.删除tcpServer中的指针、2禁用channel中事件、3删除poller中的指针。就好像这样,TcpConnection自己编写好了connectDestroyed(处理2 3事件的函数)对TcpServer说,第1个事件就交给你了TcpServer,慢着,正好我手上有一个函数,你拿去整理好了交给我。这样我最后handleClose就省不少事了。
3. 总结一下,在TcpServer中可以轻易地增加删除 TcpConnection指针,至于剩下两个事件,都需要TcpConnection自己来完成。那这两个函数给谁用呢,前者给listenChannel,后者给TcpConnection自己。
- 学习muduo(类之间的函数调用,未完成)
- 学习muduo(win平台的实现,未完成)
- 学习muduo(主要类的介绍)
- muduo网络库:线程之间的同步机制(使用eventfd函数,条件变量,线程池)
- 学习muduo(框架的设计)
- JAVA同一个类的函数(方法)之间的调用
- 类成员函数之间的调用
- muduo学习异常类
- 函数之间的相互调用
- C++学习小记(C、C++函数之间相互调用)
- VC学习(未完成)
- muduo网络库学习(七)用于创建服务器的类TcpServer
- muduo网络库学习之muduo_http 库涉及到的类
- muduo网络库学习之muduo_inspect 库涉及到的类
- muduo网络库学习之muduo_inspect 库涉及到的类
- muduo网络库学习(三)定时器TimerQueue的设计
- 在一个类里面 成员函数之间的互相调用
- 构造函数中子父类之间的调用问题
- 微信小程序------小程序初步学习
- hibernate缓存
- Hadoop Shell命令
- 通用数据存储结构
- 最小生成树prim和kruskal算法
- 学习muduo(类之间的函数调用,未完成)
- matlab提示Undefined operator '*' for input arguments of type 'cell'.
- flume简介
- Meeting HDU
- SP375 Query on a tree【树链剖分】
- Python 脚本错误:IndentationError: unindent does not match any outer indentation level
- hdu1269迷宫城堡(tarjan模板)
- CodeForces 460 A. Vasya and Socks(379A.New Year Candles)
- CodeForces 827D 浅谈最小生成树性质解析及题目性质分析