muduo_net库源码分析(25)
2013-11-07 09:20
405 查看
TCP网络编程本质
TCP网络编程最本质是的处理三个半事件
连接建立:服务器accept(被动)接受连接,客户端connect(主动)发起连接
连接断开:主动断开(close、shutdown),被动断开(read返回0)
消息到达:文件描述符可读
消息发送完毕:这算半个。对于低流量的服务,可不必关心这个事件;这里的发送完毕是指数据写入操作系统缓冲区,将由TCP协议栈负责数据的发送与重传,不代表对方已经接收到数据。
意思是说每个线程最多只能有一个EventLoop对象。
EventLoop对象构造的时候,会检查当前线程是否已经创建了其他EventLoop对象,如果已创建,终止程序(LOG_FATAL)
EventLoop构造函数会记住本对象所属线程(threadId_)。
创建了EventLoop对象的线程称为IO线程,其功能是运行事件循环(EventLoop::loop)
[/code]
EventLoop 源文件
}[/code]
[/code]
程序输出
[/code]
[/code]
程序输出
[/code]
TCP网络编程最本质是的处理三个半事件
连接建立:服务器accept(被动)接受连接,客户端connect(主动)发起连接
连接断开:主动断开(close、shutdown),被动断开(read返回0)
消息到达:文件描述符可读
消息发送完毕:这算半个。对于低流量的服务,可不必关心这个事件;这里的发送完毕是指数据写入操作系统缓冲区,将由TCP协议栈负责数据的发送与重传,不代表对方已经接收到数据。
EchoServer类图
什么都不做的EventLoop
one loop per thread意思是说每个线程最多只能有一个EventLoop对象。
EventLoop对象构造的时候,会检查当前线程是否已经创建了其他EventLoop对象,如果已创建,终止程序(LOG_FATAL)
EventLoop构造函数会记住本对象所属线程(threadId_)。
创建了EventLoop对象的线程称为IO线程,其功能是运行事件循环(EventLoop::loop)
EventLoop 头文件
EventLoop.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_EVENTLOOP_H #define MUDUO_NET_EVENTLOOP_H #include <boost/noncopyable.hpp> #include <muduo/base/CurrentThread.h> #include <muduo/base/Thread.h> namespace muduo { namespace net { /// /// Reactor, at most one per thread. /// /// This is an interface class, so don't expose too much details. class EventLoop : boost::noncopyable { public: EventLoop(); ~EventLoop(); // force out-line dtor, for scoped_ptr members. /// /// Loops forever. /// /// Must be called in the same thread as creation of the object. /// void loop(); //断言是否是当前的线程 void assertInLoopThread() { //过是当前线程,直接跳过,否则调用abortNotInLoopThread if (!isInLoopThread()) { abortNotInLoopThread(); } } //测试是否为当前线程 bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); } static EventLoop* getEventLoopOfCurrentThread(); private: void abortNotInLoopThread(); bool looping_; /* atomic , 是否处于事件循环*/ const pid_t threadId_; // 当前对象所属线程ID }; } } #endif // MUDUO_NET_EVENTLOOP_H
[/code]
EventLoop 源文件
EventLoop.cpp
// 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/EventLoop.h> #include <muduo/base/Logging.h> #include <poll.h> using namespace muduo; using namespace muduo::net; namespace { // 当前线程EventLoop对象指针 // 线程局部存储 ,如果不用__thread修饰的话,那么就是线程共共享的了 //这样达不到目标,。。 //初始化时,设为0就OK了 __thread EventLoop* t_loopInThisThread = 0; } EventLoop* EventLoop::getEventLoopOfCurrentThread() { return t_loopInThisThread; } EventLoop::EventLoop() : looping_(false), //初始化为false ,表示当前还没有处于事件循环状态 threadId_(CurrentThread::tid()) //当前的线程Id ,用于标识 { LOG_TRACE << "EventLoop created " << this << " in thread " << threadId_; // 如果当前线程已经创建了EventLoop对象,终止(LOG_FATAL),否者的话,设为当前线程this if (t_loopInThisThread) { LOG_FATAL << "Another EventLoop " << t_loopInThisThread << " exists in this thread " << threadId_; } else { t_loopInThisThread = this; } } EventLoop::~EventLoop() { t_loopInThisThread = NULL; } // 事件循环,该函数不能跨线程调用 // 只能在创建该对象的线程中调用 void EventLoop::loop() { //断言还没有事件循环 assert(!looping_); // 断言当前处于创建该对象的线程中 assertInLoopThread(); //把事件循环标识设为true looping_ = true; LOG_TRACE << "EventLoop " << this << " start looping"; //关注事件为NULL,个数为0,延时5000 ::poll(NULL, 0, 5*1000); LOG_TRACE << "EventLoop " << this << " stop looping"; //事件循环标识设为false ,这只是测试程序 looping_ = false; } //终止程序 void EventLoop::abortNotInLoopThread() { LOG_FATAL << "EventLoop::abortNotInLoopThread - EventLoop " << this << " was created in threadId_ = " << threadId_ << ", current thread id = " << CurrentThread::tid();
}[/code]
EventLoop 的测试程序1
#include <muduo/net/EventLoop.h> #include <stdio.h> using namespace muduo; using namespace muduo::net; /* 该程序 主要是用来测试EventLoop 是否是 一个Thread一个EventLoop **/ void threadFunc() { printf("threadFunc(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); EventLoop loop; loop.loop(); } int main(void) { printf("main(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); EventLoop loop; Thread t(threadFunc); t.start(); loop.loop(); t.join(); return 0; }
[/code]
程序输出
[root@localhost bin]# ./reactor_test01 main(): pid = 2724, tid = 2724 20131018 04:12:55.305234Z 2724 TRACE EventLoop EventLoop created 0xBFA6B2C0 in thread 2724 - EventLoop.cc:36 20131018 04:12:55.305599Z 2724 TRACE loop EventLoop 0xBFA6B2C0 start looping - EventLoop.cc:62 threadFunc(): pid = 2724, tid = 2725 20131018 04:12:55.305792Z 2725 TRACE EventLoop EventLoop created 0xB77E0068 in thread 2725 - EventLoop.cc:36 20131018 04:12:55.305809Z 2725 TRACE loop EventLoop 0xB77E0068 start looping - EventLoop.cc:62 20131018 04:13:00.321713Z 2724 TRACE loop EventLoop 0xBFA6B2C0 stop looping - EventLoop.cc:66 20131018 04:13:00.321779Z 2725 TRACE loop EventLoop 0xB77E0068 stop looping - EventLoop.cc:66 [root@localhost bin]#
[/code]
测试程序2
#include <muduo/net/EventLoop.h> #include <stdio.h> /** 该程序主要用来测试,多个线程使用同一个eventloop时,程序将会错误终止!! **/ using namespace muduo; using namespace muduo::net; EventLoop* g_loop; void threadFunc() { g_loop->loop(); } int main(void) { EventLoop loop; g_loop = &loop; Thread t(threadFunc); t.start(); t.join(); return 0; }
[/code]
程序输出
[root@localhost bin]# ./reactor_test02 20131018 04:15:09.010234Z 2730 TRACE EventLoop EventLoop created 0xBFD53730 in thread 2730 - EventLoop.cc:36 20131018 04:15:09.010768Z 2731 FATAL EventLoop::abortNotInLoopThread - EventLoop 0xBFD53730 was created in threadId_ = 2730, current thread id = 2731 - EventLoop.cc:72 Aborted [root@localhost bin]#
[/code]
相关文章推荐
- LINK : warning LNK4068: /MACHINE not specified; defaulting to IX86
- 关于Oracle EBS R12 表格XLA_TRANSACTION_ENTITIES 的安全策略(VPD)组研究
- ORACLE 等待事件的分类
- 多线程与并发服务器设计(23-1)
- ora_00845
- PHP识别电脑还是手机访问网站
- eclipse3.6默认指向WebContent目录修改为webRoot 设置说明 .
- tomcat6版本虚拟目录详细配置
- LogFile (22)
- traits 技术(21)
- cookie记住密码
- tomcat6版本虚拟目录详细配置
- 同一台Windows机器中启动多个Memcached服务
- 基于独立服务器SVNServer配置
- 如何在SUN的sparc平台上显示系统信息(一)
- 网秦发家-隐性的sp赚钱的暴富
- Mac OS X上搭建本地SVN服务器
- 自定义表格控件(通过TabLayout+TabRow)获取表格所有数据,并对表格进行相关事件监听
- WinCE sqlserver连接串
- sqort函数用法总结