Skip to content

Commit b1cc2ae

Browse files
authored
Add files via upload
1 parent 9a99be0 commit b1cc2ae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+6902
-0
lines changed

Acceptor.cc

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <sys/types.h>
2+
#include <sys/socket.h>
3+
#include <errno.h>
4+
#include <unistd.h>
5+
6+
#include "Acceptor.h"
7+
#include "Logger.h"
8+
#include "InetAddress.h"
9+
10+
static int createNonblocking()
11+
{
12+
int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
13+
if (sockfd < 0)
14+
{
15+
LOG_FATAL("%s:%s:%d listen socket create err:%d\n", __FILE__, __FUNCTION__, __LINE__, errno);
16+
}
17+
return sockfd;
18+
}
19+
20+
Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reuseport)
21+
: loop_(loop)
22+
, acceptSocket_(createNonblocking())
23+
, acceptChannel_(loop, acceptSocket_.fd())
24+
, listenning_(false)
25+
{
26+
acceptSocket_.setReuseAddr(true);
27+
acceptSocket_.setReusePort(true);
28+
acceptSocket_.bindAddress(listenAddr);
29+
30+
// TcpServer::start() => Acceptor.listen() 如果有新用户连接 要执行一个回调(accept => connfd => 打包成Channel => 唤醒subloop)
31+
// baseloop监听到有事件发生 => acceptChannel_(listenfd) => 执行该回调函数
32+
acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this));
33+
}
34+
35+
Acceptor::~Acceptor()
36+
{
37+
acceptChannel_.disableAll(); // 把从Poller中感兴趣的事件删除掉
38+
acceptChannel_.remove(); // 调用EventLoop->removeChannel => Poller->removeChannel 把Poller的ChannelMap对应的部分删除
39+
}
40+
41+
void Acceptor::listen()
42+
{
43+
listenning_ = true;
44+
acceptSocket_.listen(); // listen
45+
acceptChannel_.enableReading(); // acceptChannel_注册至Poller !重要
46+
}
47+
48+
// listenfd有事件发生了,就是有新用户连接了
49+
void Acceptor::handleRead()
50+
{
51+
InetAddress peerAddr;
52+
int connfd = acceptSocket_.accept(&peerAddr);
53+
if (connfd >= 0)
54+
{
55+
if (NewConnectionCallback_)
56+
{
57+
NewConnectionCallback_(connfd, peerAddr); // 轮询找到subLoop 唤醒并分发当前的新客户端的Channel
58+
}
59+
else
60+
{
61+
::close(connfd);
62+
}
63+
}
64+
else
65+
{
66+
LOG_ERROR("%s:%s:%d accept err:%d\n", __FILE__, __FUNCTION__, __LINE__, errno);
67+
if (errno == EMFILE)
68+
{
69+
LOG_ERROR("%s:%s:%d sockfd reached limit\n", __FILE__, __FUNCTION__, __LINE__);
70+
}
71+
}
72+
}

Acceptor.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
3+
#include <functional>
4+
5+
#include "noncopyable.h"
6+
#include "Socket.h"
7+
#include "Channel.h"
8+
9+
class EventLoop;
10+
class InetAddress;
11+
12+
class Acceptor : noncopyable
13+
{
14+
public:
15+
using NewConnectionCallback = std::function<void(int sockfd, const InetAddress &)>;
16+
17+
Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reuseport);
18+
~Acceptor();
19+
20+
void setNewConnectionCallback(const NewConnectionCallback &cb) { NewConnectionCallback_ = cb; }
21+
22+
bool listenning() const { return listenning_; }
23+
void listen();
24+
private:
25+
void handleRead();
26+
27+
EventLoop *loop_; // Acceptor用的就是用户定义的那个baseLoop 也称作mainLoop
28+
Socket acceptSocket_;
29+
Channel acceptChannel_;
30+
NewConnectionCallback NewConnectionCallback_;
31+
bool listenning_;
32+
};

Buffer.cc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include <errno.h>
2+
#include <sys/uio.h>
3+
#include <unistd.h>
4+
5+
#include "Buffer.h"
6+
7+
/**
8+
* 从fd上读取数据 Poller工作在LT模式
9+
* Buffer缓冲区是有大小的! 但是从fd上读取数据的时候 却不知道tcp数据的最终大小
10+
*
11+
* @description: 从socket读到缓冲区的方法是使用readv先读至buffer_,
12+
* Buffer_空间如果不够会读入到栈上65536个字节大小的空间,然后以append的
13+
* 方式追加入buffer_。既考虑了避免系统调用带来开销,又不影响数据的接收。
14+
**/
15+
ssize_t Buffer::readFd(int fd, int *saveErrno)
16+
{
17+
// 栈额外空间,用于从套接字往出读时,当buffer_暂时不够用时暂存数据,待buffer_重新分配足够空间后,在把数据交换给buffer_。
18+
char extrabuf[65536] = {0}; // 栈上内存空间 65536/1024 = 64KB
19+
20+
/*
21+
struct iovec {
22+
ptr_t iov_base; // iov_base指向的缓冲区存放的是readv所接收的数据或是writev将要发送的数据
23+
size_t iov_len; // iov_len在各种情况下分别确定了接收的最大长度以及实际写入的长度
24+
};
25+
*/
26+
27+
// 使用iovec分配两个连续的缓冲区
28+
struct iovec vec[2];
29+
const size_t writable = writableBytes(); // 这是Buffer底层缓冲区剩余的可写空间大小 不一定能完全存储从fd读出的数据
30+
31+
// 第一块缓冲区,指向可写空间
32+
vec[0].iov_base = begin() + writerIndex_;
33+
vec[0].iov_len = writable;
34+
// 第二块缓冲区,指向栈空间
35+
vec[1].iov_base = extrabuf;
36+
vec[1].iov_len = sizeof extrabuf;
37+
38+
// when there is enough space in this buffer, don't read into extrabuf.
39+
// when extrabuf is used, we read 128k-1 bytes at most.
40+
// 这里之所以说最多128k-1字节,是因为若writable为64k-1,那么需要两个缓冲区 第一个64k-1 第二个64k 所以做多128k-1
41+
// 如果第一个缓冲区>=64k 那就只采用一个缓冲区 而不使用栈空间extrabuf[65536]的内容
42+
const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1;
43+
const ssize_t n = ::readv(fd, vec, iovcnt);
44+
45+
if (n < 0)
46+
{
47+
*saveErrno = errno;
48+
}
49+
else if (n <= writable) // Buffer的可写缓冲区已经够存储读出来的数据了
50+
{
51+
writerIndex_ += n;
52+
}
53+
else // extrabuf里面也写入了n-writable长度的数据
54+
{
55+
writerIndex_ = buffer_.size();
56+
append(extrabuf, n - writable); // 对buffer_扩容 并将extrabuf存储的另一部分数据追加至buffer_
57+
}
58+
}
59+
60+
// inputBuffer_.readFd表示将对端数据读到inputBuffer_中,移动writerIndex_指针
61+
// outputBuffer_.writeFd标示将数据写入到outputBuffer_中,从readerIndex_开始,可以写readableBytes()个字节
62+
ssize_t Buffer::writeFd(int fd, int *saveErrno)
63+
{
64+
ssize_t n = ::write(fd, peek(), readableBytes());
65+
if (n < 0)
66+
{
67+
*saveErrno = errno;
68+
}
69+
return n;
70+
}

Buffer.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <string>
5+
#include <algorithm>
6+
#include <stddef.h>
7+
8+
// 网络库底层的缓冲区类型定义
9+
class Buffer
10+
{
11+
public:
12+
static const size_t kCheapPrepend = 8;
13+
static const size_t kInitialSize = 1024;
14+
15+
explicit Buffer(size_t initalSize = kInitialSize)
16+
: buffer_(kCheapPrepend + initalSize)
17+
, readerIndex_(kCheapPrepend)
18+
, writerIndex_(kCheapPrepend)
19+
{
20+
}
21+
22+
size_t readableBytes() const { return writerIndex_ - readerIndex_; }
23+
size_t writableBytes() const { return buffer_.size() - writerIndex_; }
24+
size_t prependableBytes() const { return readerIndex_; }
25+
26+
// 返回缓冲区中可读数据的起始地址
27+
const char *peek() const { return begin() + readerIndex_; }
28+
void retrieve(size_t len)
29+
{
30+
if (len < readableBytes())
31+
{
32+
readerIndex_ += len; // 说明应用只读取了可读缓冲区数据的一部分,就是len长度 还剩下readerIndex+=len到writerIndex_的数据未读
33+
}
34+
else // len == readableBytes()
35+
{
36+
retrieveAll();
37+
}
38+
}
39+
void retrieveAll()
40+
{
41+
readerIndex_ = kCheapPrepend;
42+
writerIndex_ = kCheapPrepend;
43+
}
44+
45+
// 把onMessage函数上报的Buffer数据 转成string类型的数据返回
46+
std::string retrieveAllAsString() { return retrieveAsString(readableBytes()); }
47+
std::string retrieveAsString(size_t len)
48+
{
49+
std::string result(peek(), len);
50+
retrieve(len); // 上面一句把缓冲区中可读的数据已经读取出来 这里肯定要对缓冲区进行复位操作
51+
return result;
52+
}
53+
54+
// buffer_.size - writerIndex_
55+
void ensureWritableBytes(size_t len)
56+
{
57+
if (writableBytes() < len)
58+
{
59+
makeSpace(len); // 扩容
60+
}
61+
}
62+
63+
// 把[data, data+len]内存上的数据添加到writable缓冲区当中
64+
void append(const char *data, size_t len)
65+
{
66+
ensureWritableBytes(len);
67+
std::copy(data, data+len, beginWrite());
68+
writerIndex_ += len;
69+
}
70+
char *beginWrite() { return begin() + writerIndex_; }
71+
const char *beginWrite() const { return begin() + writerIndex_; }
72+
73+
// 从fd上读取数据
74+
ssize_t readFd(int fd, int *saveErrno);
75+
// 通过fd发送数据
76+
ssize_t writeFd(int fd, int *saveErrno);
77+
78+
private:
79+
// vector底层数组首元素的地址 也就是数组的起始地址
80+
char *begin() { return &*buffer_.begin(); }
81+
const char *begin() const { return &*buffer_.begin(); }
82+
83+
void makeSpace(size_t len)
84+
{
85+
/**
86+
* | kCheapPrepend |xxx|reader | writer | // xxx标示reader中已读的部分
87+
* | kCheapPrepend | len |
88+
**/
89+
if (writableBytes() + prependableBytes() < len + kCheapPrepend) // 也就是说 len > xxx + writer的部分
90+
{
91+
buffer_.resize(writerIndex_ + len);
92+
}
93+
else // 这里说明 len <= xxx + writer 把reader搬到从xxx开始 使得xxx后面是一段连续空间
94+
{
95+
size_t readable = readableBytes(); // readable = reader的长度
96+
std::copy(begin()+readerIndex_, begin()+writerIndex_, // 把这一部分数据拷贝到begin+kCheapPrepend起始处
97+
begin()+kCheapPrepend);
98+
readerIndex_ = kCheapPrepend;
99+
writerIndex_ = readerIndex_+readable;
100+
}
101+
}
102+
103+
std::vector<char> buffer_;
104+
size_t readerIndex_;
105+
size_t writerIndex_;
106+
};

CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 2.5)
2+
project(mymuduo)
3+
4+
# mymuduo最终编译成so动态库 设置动态库的路径 放置项目根目录的lib文件夹下面
5+
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
6+
7+
# 设置调试信息 以及启动C++11语言标准
8+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11")
9+
10+
# 定义参与编译的源代码文件
11+
aux_source_directory(. SRC_LIST)
12+
13+
# 编译动态库
14+
add_library(mymuduo SHARED ${SRC_LIST})

Callbacks.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <functional>
5+
6+
class Buffer;
7+
class TcpConnection;
8+
class Timestamp;
9+
10+
using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
11+
using ConnectionCallback = std::function<void(const TcpConnectionPtr &)>;
12+
using CloseCallback = std::function<void(const TcpConnectionPtr &)>;
13+
using WriteCompleteCallback = std::function<void(const TcpConnectionPtr &)>;
14+
using HighWaterMarkCallback = std::function<void(const TcpConnectionPtr &, size_t)>;
15+
16+
using MessageCallback = std::function<void(const TcpConnectionPtr &,
17+
Buffer *,
18+
Timestamp)>;

0 commit comments

Comments
 (0)