Skip to content

Commit fbfbec0

Browse files
author
herongwei
committed
add muduo code notes
1 parent 8e895c5 commit fbfbec0

File tree

5 files changed

+528
-0
lines changed

5 files changed

+528
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2021. rongweihe All rights reserved.
2+
// https://github.com/rongweihe/CPPNotes/tree/master/NetPrograming
3+
//
4+
// Use of this source code is governed by a BSD-style license
5+
// that can be found in the License file.
6+
//
7+
// This is a public header file, it must only include public header files.
8+
9+
#include "muduo/net/Acceptor.h"
10+
11+
#include "muduo/base/Logging.h"
12+
#include "muduo/net/EventLoop.h"
13+
#include "muduo/net/InetAddress.h"
14+
#include "muduo/net/SocketsOps.h"
15+
16+
#include <errno.h>
17+
#include <fcntl.h>
18+
//#include <sys/types.h>
19+
//#include <sys/stat.h>
20+
#include <unistd.h>
21+
22+
using namespace muduo;
23+
using namespace muduo::net;
24+
25+
//Acceptor的 socket 是 listen socket channel 用于观察此 socket 的 readable 事件 并回调 handleRead 后者会调用 accept 接受连接
26+
//构造函数执行创建 TCP 服务端的传统步骤: Socket bind listen (acceptSocket_ 封装了其步骤) 创建了非阻塞的 socket
27+
Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport)
28+
: loop_(loop),
29+
acceptSocket_(sockets::createNonblockingOrDie(listenAddr.family())),
30+
acceptChannel_(loop, acceptSocket_.fd()),
31+
listening_(false),
32+
idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC))
33+
{
34+
assert(idleFd_ >= 0);
35+
acceptSocket_.setReuseAddr(true);
36+
acceptSocket_.setReusePort(reuseport);
37+
acceptSocket_.bindAddress(listenAddr);
38+
acceptChannel_.setReadCallback(
39+
std::bind(&Acceptor::handleRead, this));
40+
}
41+
42+
Acceptor::~Acceptor()
43+
{
44+
acceptChannel_.disableAll();
45+
acceptChannel_.remove();
46+
::close(idleFd_);
47+
}
48+
49+
void Acceptor::listen()
50+
{
51+
loop_->assertInLoopThread();
52+
listening_ = true;
53+
acceptSocket_.listen();
54+
acceptChannel_.enableReading();
55+
}
56+
57+
//socket 可读的时候调用 Acceptor::handleRead 后者会接受 accept 并回调 newConnectionCallback_
58+
void Acceptor::handleRead()
59+
{
60+
loop_->assertInLoopThread();
61+
InetAddress peerAddr;
62+
//FIXME loop until no more
63+
int connfd = acceptSocket_.accept(&peerAddr);
64+
if (connfd >= 0)
65+
{
66+
// string hostport = peerAddr.toIpPort();
67+
// LOG_TRACE << "Accepts of " << hostport;
68+
if (newConnectionCallback_)
69+
{
70+
newConnectionCallback_(connfd, peerAddr);
71+
}
72+
else
73+
{
74+
sockets::close(connfd);
75+
}
76+
}
77+
else
78+
{
79+
LOG_SYSERR << "in Acceptor::handleRead";
80+
// Read the section named "The special problem of
81+
// accept()ing when you can't" in libev's doc.
82+
// By Marc Lehmann, author of libev.
83+
if (errno == EMFILE)
84+
{
85+
::close(idleFd_);
86+
idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL);
87+
::close(idleFd_);
88+
idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);
89+
}
90+
}
91+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2021. rongweihe All rights reserved.
2+
// https://github.com/rongweihe/CPPNotes/tree/master/NetPrograming
3+
//
4+
// Use of this source code is governed by a BSD-style license
5+
// that can be found in the License file.
6+
//
7+
// This is a public header file, it must only include public header files.
8+
9+
10+
#ifndef MUDUO_NET_ACCEPTOR_H
11+
#define MUDUO_NET_ACCEPTOR_H
12+
13+
#include <functional>
14+
15+
#include "muduo/net/Channel.h"
16+
#include "muduo/net/Socket.h"
17+
18+
namespace muduo
19+
{
20+
namespace net
21+
{
22+
23+
class EventLoop;
24+
class InetAddress;
25+
///
26+
/// Acceptor of incoming TCP connections.
27+
/// acceptor 负责 accept 新连接,并将新连接分发到 subReactor。
28+
class Acceptor : noncopyable
29+
{
30+
31+
public:
32+
typedef std::function<void (int sockfd, const InetAddress&)> NewConnectionCallback;
33+
Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport);
34+
~Acceptor();
35+
36+
void setNewConnectionCallback(const NewConnectionCallback& cb)
37+
{ newConnectionCallback_ = cb; }
38+
39+
void listen();
40+
41+
bool listening() const { return listening_; }
42+
43+
// Deprecated, use the correct spelling one above.
44+
// Leave the wrong spelling here in case one needs to grep it for error messages.
45+
// bool listenning() const { return listening(); }
46+
47+
private:
48+
void handleRead();
49+
EventLoop* loop_;
50+
Socket acceptSocket_;
51+
Channel acceptChannel_;
52+
NewConnectionCallback newConnectionCallback_;
53+
bool listening_;
54+
int idleFd_;
55+
};
56+
57+
} //namespace net
58+
} //namespace muduo
59+
60+
#endif // MUDUO_NET_ACCEPTOR_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2021 rongweihe. All rights reserved.
2+
// https://github.com/rongweihe/CPPNotes/tree/master/NetPrograming
3+
//
4+
// Use of this source code is governed by a BSD-style license
5+
// that can be found in the License file.
6+
7+
8+
#include "muduo/net/EventLoopThreadPool.h"
9+
10+
#include "muduo/net/EventLoop.h"
11+
#include "muduo/net/EventLoopThread.h"
12+
13+
#include <stdio.h>
14+
15+
using namespace muduo;
16+
using namespace muduo::net;
17+
18+
EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, const string& nameArg)
19+
: baseLoop_(baseLoop),
20+
name_(nameArg),
21+
started_(fasle),
22+
numThreads_(0),
23+
next_(0)
24+
{
25+
26+
}
27+
28+
EventLoopThreadPool::~EventLoopThreadPool()
29+
{
30+
// Don't delete loop, it's stack variable
31+
}
32+
33+
// round-robin 算法选择下一个 loop
34+
//轮询调度(Round Robin Scheduling)算法就是以轮询的方式依次将请求调度不同的服务器,
35+
//即每次调度执行i = (i + 1) mod n,并选出第i台服务器。 算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。
36+
EventLoop* EventLoopThreadPool::getNextLoop()
37+
{
38+
baseLoop_->assertInLoopThread();
39+
assert(started_);
40+
EventLoop* loop = baseLoop_;
41+
42+
if (!loops_.empty())
43+
{
44+
//rounf-robin
45+
loop = loops_[next_];
46+
++next_;
47+
if (implicit_cast<size_t>(next_) >= loops_.size())
48+
{
49+
next_ = 0;
50+
}
51+
}
52+
return loop;
53+
}
54+
55+
EventLoop* EventLoopThreadPool::getLoopForHash(size_t hashCode)
56+
{
57+
baseLoop_->assertInLoopThread();
58+
EventLoop* loop = baseLoop_;
59+
60+
if (!loops_.empty())
61+
{
62+
loop = loops_[hashCode % loops_.size()];
63+
}
64+
return loop;
65+
}
66+
67+
//返回所有的loops
68+
std::vector<EventLoop*> EventLoopThreadPool::getAllLoops()
69+
{
70+
baseLoop_->assertInLoopThread();
71+
assert(started_);
72+
if (loops_.empty())
73+
{
74+
return std::vector<EventLoop*>(1, baseLoop_);
75+
}
76+
else
77+
{
78+
return loops_;
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2021. rongweihe All rights reserved.
2+
// https://github.com/rongweihe/CPPNotes/tree/master/NetPrograming
3+
//
4+
// Use of this source code is governed by a BSD-style license
5+
// that can be found in the License file.
6+
//
7+
// This is a public header file, it must only include public header files.
8+
9+
#ifndef MUDUO_NET_EVENTLOOPTHREAD_H
10+
#define MUDUO_NET_EVENTLOOPTHREAD_H
11+
12+
#include "muduo/base/Condition.h"
13+
#include "muduo/base/Mutex.h"
14+
#include "muduo/base/Thread.h"
15+
16+
namespace muduo
17+
{
18+
namespace net
19+
{
20+
21+
class EventLoop;
22+
class EventLoopThread : noncopyable
23+
{
24+
public:
25+
typedef std::function<void(EventLoop*)> ThreadInitCallback;
26+
EventLoopThread(const ThreadInitCallback& cb = ThreadInitCallback(),
27+
const string& name = string());
28+
~EventLoopThread();
29+
EventLoop* startLoop();
30+
private:
31+
void threadFunc();
32+
EventLoop* loop_ GUARDED_BY(mutex_);
33+
bool exiting_;
34+
Thread thread_;
35+
MutexLock mutex_;
36+
Condition cond_ GUARDED_BY(mutex_);
37+
ThreadInitCallback callback_;
38+
};
39+
40+
} //namespace net
41+
} //namespace muduo

0 commit comments

Comments
 (0)