Showing preview only (1,538K chars total). Download the full file or copy to clipboard to get everything.
Repository: yuesong-feng/30dayMakeCppServer
Branch: main
Commit: 5e3386d6d89b
Files: 370
Total size: 1.4 MB
Directory structure:
gitextract_3td5mg8d/
├── README.md
├── code/
│ ├── day01/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ └── server.cpp
│ ├── day02/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day03/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day04/
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Makefile
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day05/
│ │ ├── Channel.cpp
│ │ ├── Channel.h
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Makefile
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day06/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ └── src/
│ │ ├── Channel.cpp
│ │ ├── Channel.h
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── EventLoop.cpp
│ │ ├── EventLoop.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Server.cpp
│ │ ├── Server.h
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day07/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ └── src/
│ │ ├── Acceptor.cpp
│ │ ├── Acceptor.h
│ │ ├── Channel.cpp
│ │ ├── Channel.h
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── EventLoop.cpp
│ │ ├── EventLoop.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Server.cpp
│ │ ├── Server.h
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day08/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ └── src/
│ │ ├── Acceptor.cpp
│ │ ├── Acceptor.h
│ │ ├── Channel.cpp
│ │ ├── Channel.h
│ │ ├── Connection.cpp
│ │ ├── Connection.h
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── EventLoop.cpp
│ │ ├── EventLoop.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Server.cpp
│ │ ├── Server.h
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day09/
│ │ ├── Makefile
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ └── src/
│ │ ├── Acceptor.cpp
│ │ ├── Acceptor.h
│ │ ├── Buffer.cpp
│ │ ├── Buffer.h
│ │ ├── Channel.cpp
│ │ ├── Channel.h
│ │ ├── Connection.cpp
│ │ ├── Connection.h
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── EventLoop.cpp
│ │ ├── EventLoop.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Server.cpp
│ │ ├── Server.h
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day10/
│ │ ├── Makefile
│ │ ├── ThreadPoolTest.cpp
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ └── src/
│ │ ├── Acceptor.cpp
│ │ ├── Acceptor.h
│ │ ├── Buffer.cpp
│ │ ├── Buffer.h
│ │ ├── Channel.cpp
│ │ ├── Channel.h
│ │ ├── Connection.cpp
│ │ ├── Connection.h
│ │ ├── Epoll.cpp
│ │ ├── Epoll.h
│ │ ├── EventLoop.cpp
│ │ ├── EventLoop.h
│ │ ├── InetAddress.cpp
│ │ ├── InetAddress.h
│ │ ├── Server.cpp
│ │ ├── Server.h
│ │ ├── Socket.cpp
│ │ ├── Socket.h
│ │ ├── ThreadPool.cpp
│ │ ├── ThreadPool.h
│ │ ├── util.cpp
│ │ └── util.h
│ ├── day11/
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── Makefile
│ │ ├── ThreadPoolTest.cpp
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ ├── src/
│ │ │ ├── Acceptor.cpp
│ │ │ ├── Acceptor.h
│ │ │ ├── Buffer.cpp
│ │ │ ├── Buffer.h
│ │ │ ├── Channel.cpp
│ │ │ ├── Channel.h
│ │ │ ├── Connection.cpp
│ │ │ ├── Connection.h
│ │ │ ├── Epoll.cpp
│ │ │ ├── Epoll.h
│ │ │ ├── EventLoop.cpp
│ │ │ ├── EventLoop.h
│ │ │ ├── InetAddress.cpp
│ │ │ ├── InetAddress.h
│ │ │ ├── Server.cpp
│ │ │ ├── Server.h
│ │ │ ├── Socket.cpp
│ │ │ ├── Socket.h
│ │ │ ├── ThreadPool.cpp
│ │ │ ├── ThreadPool.h
│ │ │ ├── util.cpp
│ │ │ └── util.h
│ │ └── test.cpp
│ ├── day12/
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── Makefile
│ │ ├── ThreadPoolTest.cpp
│ │ ├── client.cpp
│ │ ├── server.cpp
│ │ ├── src/
│ │ │ ├── Acceptor.cpp
│ │ │ ├── Acceptor.h
│ │ │ ├── Buffer.cpp
│ │ │ ├── Buffer.h
│ │ │ ├── Channel.cpp
│ │ │ ├── Channel.h
│ │ │ ├── Connection.cpp
│ │ │ ├── Connection.h
│ │ │ ├── Epoll.cpp
│ │ │ ├── Epoll.h
│ │ │ ├── EventLoop.cpp
│ │ │ ├── EventLoop.h
│ │ │ ├── Server.cpp
│ │ │ ├── Server.h
│ │ │ ├── Socket.cpp
│ │ │ ├── Socket.h
│ │ │ ├── ThreadPool.cpp
│ │ │ ├── ThreadPool.h
│ │ │ ├── util.cpp
│ │ │ └── util.h
│ │ └── test.cpp
│ ├── day13/
│ │ ├── .clang-format
│ │ ├── .clang-tidy
│ │ ├── .gitignore
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── CMakeLists.txt
│ │ ├── build_support/
│ │ │ ├── clang_format_exclusions.txt
│ │ │ ├── cpplint.py
│ │ │ ├── run_clang_format.py
│ │ │ ├── run_clang_tidy.py
│ │ │ └── run_clang_tidy_extra.py
│ │ ├── src/
│ │ │ ├── Acceptor.cpp
│ │ │ ├── Buffer.cpp
│ │ │ ├── CMakeLists.txt
│ │ │ ├── Channel.cpp
│ │ │ ├── Connection.cpp
│ │ │ ├── Epoll.cpp
│ │ │ ├── EventLoop.cpp
│ │ │ ├── Server.cpp
│ │ │ ├── Socket.cpp
│ │ │ ├── ThreadPool.cpp
│ │ │ ├── include/
│ │ │ │ ├── Acceptor.h
│ │ │ │ ├── Buffer.h
│ │ │ │ ├── Channel.h
│ │ │ │ ├── Connection.h
│ │ │ │ ├── Epoll.h
│ │ │ │ ├── EventLoop.h
│ │ │ │ ├── Macros.h
│ │ │ │ ├── Server.h
│ │ │ │ ├── Socket.h
│ │ │ │ ├── ThreadPool.h
│ │ │ │ └── util.h
│ │ │ └── util.cpp
│ │ └── test/
│ │ ├── CMakeLists.txt
│ │ ├── multiple_client.cpp
│ │ ├── server.cpp
│ │ ├── single_client.cpp
│ │ └── thread_test.cpp
│ ├── day14/
│ │ ├── .clang-format
│ │ ├── .clang-tidy
│ │ ├── .gitignore
│ │ ├── .vscode/
│ │ │ └── launch.json
│ │ ├── CMakeLists.txt
│ │ ├── build_support/
│ │ │ ├── clang_format_exclusions.txt
│ │ │ ├── cpplint.py
│ │ │ ├── run_clang_format.py
│ │ │ ├── run_clang_tidy.py
│ │ │ └── run_clang_tidy_extra.py
│ │ ├── src/
│ │ │ ├── Acceptor.cpp
│ │ │ ├── Buffer.cpp
│ │ │ ├── CMakeLists.txt
│ │ │ ├── Channel.cpp
│ │ │ ├── Connection.cpp
│ │ │ ├── Epoll.cpp
│ │ │ ├── EventLoop.cpp
│ │ │ ├── Server.cpp
│ │ │ ├── Socket.cpp
│ │ │ ├── ThreadPool.cpp
│ │ │ ├── include/
│ │ │ │ ├── Acceptor.h
│ │ │ │ ├── Buffer.h
│ │ │ │ ├── Channel.h
│ │ │ │ ├── Connection.h
│ │ │ │ ├── Epoll.h
│ │ │ │ ├── EventLoop.h
│ │ │ │ ├── Macros.h
│ │ │ │ ├── Server.h
│ │ │ │ ├── Socket.h
│ │ │ │ ├── ThreadPool.h
│ │ │ │ └── util.h
│ │ │ └── util.cpp
│ │ └── test/
│ │ ├── CMakeLists.txt
│ │ ├── multiple_client.cpp
│ │ ├── server.cpp
│ │ ├── single_client.cpp
│ │ └── thread_test.cpp
│ ├── day15/
│ │ ├── .clang-format
│ │ ├── .clang-tidy
│ │ ├── .gitignore
│ │ ├── CMakeLists.txt
│ │ ├── build_support/
│ │ │ ├── clang_format_exclusions.txt
│ │ │ ├── cpplint.py
│ │ │ ├── run_clang_format.py
│ │ │ ├── run_clang_tidy.py
│ │ │ └── run_clang_tidy_extra.py
│ │ ├── src/
│ │ │ ├── Acceptor.cpp
│ │ │ ├── Buffer.cpp
│ │ │ ├── CMakeLists.txt
│ │ │ ├── Channel.cpp
│ │ │ ├── Connection.cpp
│ │ │ ├── EventLoop.cpp
│ │ │ ├── Poller.cpp
│ │ │ ├── Server.cpp
│ │ │ ├── Socket.cpp
│ │ │ ├── ThreadPool.cpp
│ │ │ ├── include/
│ │ │ │ ├── Acceptor.h
│ │ │ │ ├── Buffer.h
│ │ │ │ ├── Channel.h
│ │ │ │ ├── Connection.h
│ │ │ │ ├── EventLoop.h
│ │ │ │ ├── Exception.h
│ │ │ │ ├── Log.h
│ │ │ │ ├── Macros.h
│ │ │ │ ├── Poller.h
│ │ │ │ ├── Server.h
│ │ │ │ ├── SignalHandler.h
│ │ │ │ ├── Socket.h
│ │ │ │ ├── ThreadPool.h
│ │ │ │ ├── pine.h
│ │ │ │ └── util.h
│ │ │ └── util.cpp
│ │ └── test/
│ │ ├── CMakeLists.txt
│ │ ├── chat_client.cpp
│ │ ├── chat_server.cpp
│ │ ├── echo_client.cpp
│ │ ├── echo_clients.cpp
│ │ ├── echo_server.cpp
│ │ └── http_server.cpp
│ └── day16/
│ ├── .clang-format
│ ├── .clang-tidy
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── build_support/
│ │ ├── clang_format_exclusions.txt
│ │ ├── cpplint.py
│ │ ├── run_clang_format.py
│ │ ├── run_clang_tidy.py
│ │ └── run_clang_tidy_extra.py
│ ├── src/
│ │ ├── Acceptor.cpp
│ │ ├── Buffer.cpp
│ │ ├── CMakeLists.txt
│ │ ├── Channel.cpp
│ │ ├── Connection.cpp
│ │ ├── EventLoop.cpp
│ │ ├── Poller.cpp
│ │ ├── Socket.cpp
│ │ ├── TcpServer.cpp
│ │ ├── ThreadPool.cpp
│ │ └── include/
│ │ ├── Acceptor.h
│ │ ├── Buffer.h
│ │ ├── Channel.h
│ │ ├── Connection.h
│ │ ├── EventLoop.h
│ │ ├── Exception.h
│ │ ├── Log.h
│ │ ├── Poller.h
│ │ ├── SignalHandler.h
│ │ ├── Socket.h
│ │ ├── TcpServer.h
│ │ ├── ThreadPool.h
│ │ ├── common.h
│ │ └── pine.h
│ └── test/
│ ├── CMakeLists.txt
│ ├── chat_client.cpp
│ ├── chat_server.cpp
│ ├── echo_client.cpp
│ ├── echo_clients.cpp
│ ├── echo_server.cpp
│ └── http_server.cpp
├── day01-从一个最简单的socket开始.md
├── day02-不要放过任何一个错误.md
├── day03-高并发还得用epoll.md
├── day04-来看看我们的第一个类.md
├── day05-epoll高级用法-Channel登场.md
├── day06-服务器与事件驱动核心类登场.md
├── day07-为我们的服务器添加一个Acceptor.md
├── day08-一切皆是类,连TCP连接也不例外.md
├── day09-缓冲区-大作用.md
├── day10-加入线程池到服务器.md
├── day11-完善线程池,加入一个简单的测试程序.md
├── day12-将服务器改写为主从Reactor多线程模式.md
├── day13-C++工程化、代码分析、性能优化.md
├── day14-支持业务逻辑自定义、完善Connection类.md
├── day15-macOS支持、完善业务逻辑自定义.md
└── day16-重构核心库、使用智能指针.md
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# 30天自制C++服务器
> 该教程是本人学生时代初学C++的历程,工作后已无精力写完剩下部分,回顾当年的代码有诸多不完美甚至瑕疵,有意愿者可以自由修改、开发、续写该项目。
先说结论:不管使用什么语言,一切后台开发的根基,是面向Linux的C/C++服务器开发。
几乎所有高并发服务器都是运行在Linux环境的,笔者之前也用Java、node写过服务器,但最后发现只是学会了一门技术、一门语言,而并不了解底层的基础原理。一个HTTP请求的过程,为什么可以实现高并发,如何控制TCP连接,如何处理好数据传输的逻辑等等,这些只有面向C/C++编程才能深入了解。
本教程模仿《30天自制操作系统》,面向零经验的新手,教你在30天内入门Linux服务器开发。本教程更偏向实践,将会把重点放在如何写代码上,而不会花太多的篇幅讲解背后的计算机基础原理,涉及到的地方会给出相应书籍的具体章节,但这并不代表这些理论知识不重要,事实上理论基础相当重要,没有理论的支撑,构建出一个高性能服务器是无稽之谈。
本教程希望读者:
- 熟悉C/C++语言
- 熟悉计算机网络基础,如TCP协议、socket原理等
- 了解基本的操作系统基础概念,如进程、线程、内存资源、系统调用等
学完本教程后,你将会很轻松地看懂muduo源码。
C/C++学习的一个难点在于初学时无法做出实际上的东西,没有反馈,程序都在黑乎乎的命令行里运行,不像web开发,可以随时看到自己学习的成果。本教程的代码都放在code文件夹里,每一天学习后都可以得到一个可以编译运行的服务器,不断迭代开发。
在code文件夹里有每一天的代码文件夹,进入该文件夹,使用`make`命令编译,会生成两个可执行文件,输入命令`./server`就能看到今天的学习成果!然后新建一个Terminal,然后输入`./client`运行客户端,与服务器交互。
[day01-从一个最简单的socket开始](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day01-从一个最简单的socket开始.md)
[day02-不要放过任何一个错误](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day02-不要放过任何一个错误.md)
[day03-高并发还得用epoll](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day03-高并发还得用epoll.md)
[day04-来看看我们的第一个类](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day04-来看看我们的第一个类.md)
[day05-epoll高级用法-Channel登场](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day05-epoll高级用法-Channel登场.md)
[day06-服务器与事件驱动核心类登场](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day06-服务器与事件驱动核心类登场.md)
[day07-为我们的服务器添加一个Acceptor](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day07-为我们的服务器添加一个Acceptor.md)
[day08-一切皆是类,连TCP连接也不例外](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day08-一切皆是类,连TCP连接也不例外.md)
[day09-缓冲区-大作用](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day09-缓冲区-大作用.md)
[day10-加入线程池到服务器](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day10-加入线程池到服务器.md)
[day11-完善线程池,加入一个简单的测试程序](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day11-完善线程池,加入一个简单的测试程序.md)
[day12-将服务器改写为主从Reactor多线程模式](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day12-将服务器改写为主从Reactor多线程模式.md)
[day13-C++工程化、代码分析、性能优化](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day13-C++工程化、代码分析、性能优化.md)
[day14-支持业务逻辑自定义、完善Connection类](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day14-支持业务逻辑自定义、完善Connection类.md)
[day15-macOS支持、完善业务逻辑自定义](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day15-macOS支持、完善业务逻辑自定义.md)
[day16-重构服务器、使用智能指针](https://github.com/yuesong-feng/30dayMakeCppServer/blob/main/day16-重构核心库、使用智能指针.md)
[Wlgls/30daysCppWebServer](https://github.com/Wlgls/30daysCppWebServer)项目尝试续写了后续部分,可供学习参考
## Contribute
能力一般、水平有限,如果发现我的教程有不正确或者值得改进的地方,欢迎提issue或直接PR。
欢迎大家为本项目贡献自己的代码,如果有你觉得更好的代码,请提issue或者直接PR,所有建议都会被考虑。
贡献代码请到[pine](https://github.com/yuesong-feng/pine)项目,这是本教程开发的网络库,也是最新的代码版本。
================================================
FILE: code/day01/Makefile
================================================
server:
g++ server.cpp -o server && g++ client.cpp -o client
================================================
FILE: code/day01/client.cpp
================================================
/*
* @Author: your name
* @Date: 2022-01-04 20:03:45
* @LastEditTime: 2022-01-05 19:08:58
* @LastEditors: your name
* @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @FilePath: \30dayMakeCppServer\code\day01\client.cpp
*/
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
//bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)); 客户端不进行bind操作
connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr));
return 0;
}
================================================
FILE: code/day01/server.cpp
================================================
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr));
listen(sockfd, SOMAXCONN);
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_len = sizeof(clnt_addr);
bzero(&clnt_addr, sizeof(clnt_addr));
int clnt_sockfd = accept(sockfd, (sockaddr*)&clnt_addr, &clnt_addr_len);
printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));
return 0;
}
================================================
FILE: code/day02/Makefile
================================================
server:
g++ util.cpp client.cpp -o client && \
g++ util.cpp server.cpp -o server
clean:
rm server && rm client
================================================
FILE: code/day02/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[1024];
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day02/server.cpp
================================================
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket bind error");
errif(listen(sockfd, SOMAXCONN) == -1, "socket listen error");
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_len = sizeof(clnt_addr);
bzero(&clnt_addr, sizeof(clnt_addr));
int clnt_sockfd = accept(sockfd, (sockaddr*)&clnt_addr, &clnt_addr_len);
errif(clnt_sockfd == -1, "socket accept error");
printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));
while (true) {
char buf[1024];
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(clnt_sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from client fd %d: %s\n", clnt_sockfd, buf);
write(clnt_sockfd, buf, sizeof(buf));
} else if(read_bytes == 0){
printf("client fd %d disconnected\n", clnt_sockfd);
close(clnt_sockfd);
break;
} else if(read_bytes == -1){
close(clnt_sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day02/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day02/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day03/Makefile
================================================
server:
g++ util.cpp client.cpp -o client && \
g++ util.cpp server.cpp -o server
clean:
rm server && rm client
================================================
FILE: code/day03/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么?
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day03/server.cpp
================================================
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <errno.h>
#include "util.h"
#define MAX_EVENTS 1024
#define READ_BUFFER 1024
void setnonblocking(int fd){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket bind error");
errif(listen(sockfd, SOMAXCONN) == -1, "socket listen error");
int epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
struct epoll_event events[MAX_EVENTS], ev;
bzero(&events, sizeof(events));
bzero(&ev, sizeof(ev));
ev.data.fd = sockfd;
ev.events = EPOLLIN | EPOLLET;
setnonblocking(sockfd);
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
while(true){
int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
if(events[i].data.fd == sockfd){ //新客户端连接
struct sockaddr_in clnt_addr;
bzero(&clnt_addr, sizeof(clnt_addr));
socklen_t clnt_addr_len = sizeof(clnt_addr);
int clnt_sockfd = accept(sockfd, (sockaddr*)&clnt_addr, &clnt_addr_len);
errif(clnt_sockfd == -1, "socket accept error");
printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));
bzero(&ev, sizeof(ev));
ev.data.fd = clnt_sockfd;
ev.events = EPOLLIN | EPOLLET;
setnonblocking(clnt_sockfd);
epoll_ctl(epfd, EPOLL_CTL_ADD, clnt_sockfd, &ev);
} else if(events[i].events & EPOLLIN){ //可读事件
char buf[READ_BUFFER];
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(events[i].data.fd, buf, sizeof(buf));
if(bytes_read > 0){
printf("message from client fd %d: %s\n", events[i].data.fd, buf);
write(events[i].data.fd, buf, sizeof(buf));
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once, errno: %d\n", errno);
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", events[i].data.fd);
close(events[i].data.fd); //关闭socket会自动将文件描述符从epoll树上移除
break;
}
}
} else{ //其他事件,之后的版本实现
printf("something else happened\n");
}
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day03/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day03/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day04/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
void Epoll::addFd(int fd, uint32_t op){
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.fd = fd;
ev.events = op;
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
}
std::vector<epoll_event> Epoll::poll(int timeout){
std::vector<epoll_event> activeEvents;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
activeEvents.push_back(events[i]);
}
return activeEvents;
}
================================================
FILE: code/day04/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
void addFd(int fd, uint32_t op);
std::vector<epoll_event> poll(int timeout = -1);
};
================================================
FILE: code/day04/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
================================================
FILE: code/day04/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
public:
struct sockaddr_in addr;
socklen_t addr_len;
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
};
================================================
FILE: code/day04/Makefile
================================================
server:
g++ util.cpp client.cpp -o client && \
g++ util.cpp server.cpp Epoll.cpp InetAddress.cpp Socket.cpp -o server
clean:
rm server && rm client
================================================
FILE: code/day04/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *addr){
errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error");
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *addr){
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len);
errif(clnt_sockfd == -1, "socket accept error");
return clnt_sockfd;
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day04/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
int getFd();
};
================================================
FILE: code/day04/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么?
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day04/server.cpp
================================================
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <vector>
#include "util.h"
#include "Epoll.h"
#include "InetAddress.h"
#include "Socket.h"
#define MAX_EVENTS 1024
#define READ_BUFFER 1024
void setnonblocking(int fd){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
void handleReadEvent(int);
int main() {
Socket *serv_sock = new Socket();
InetAddress *serv_addr = new InetAddress("127.0.0.1", 8888);
serv_sock->bind(serv_addr);
serv_sock->listen();
Epoll *ep = new Epoll();
serv_sock->setnonblocking();
ep->addFd(serv_sock->getFd(), EPOLLIN | EPOLLET);
while(true){
std::vector<epoll_event> events = ep->poll();
int nfds = events.size();
for(int i = 0; i < nfds; ++i){
if(events[i].data.fd == serv_sock->getFd()){ //新客户端连接
InetAddress *clnt_addr = new InetAddress(); //会发生内存泄露!没有delete
Socket *clnt_sock = new Socket(serv_sock->accept(clnt_addr)); //会发生内存泄露!没有delete
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->addr.sin_addr), ntohs(clnt_addr->addr.sin_port));
clnt_sock->setnonblocking();
ep->addFd(clnt_sock->getFd(), EPOLLIN | EPOLLET);
} else if(events[i].events & EPOLLIN){ //可读事件
handleReadEvent(events[i].data.fd);
} else{ //其他事件,之后的版本实现
printf("something else happened\n");
}
}
}
delete serv_sock;
delete serv_addr;
return 0;
}
void handleReadEvent(int sockfd){
char buf[READ_BUFFER];
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
printf("message from client fd %d: %s\n", sockfd, buf);
write(sockfd, buf, sizeof(buf));
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once, errno: %d\n", errno);
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
break;
}
}
}
================================================
FILE: code/day04/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day04/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day05/Channel.cpp
================================================
#include "Channel.h"
#include "Epoll.h"
Channel::Channel(Epoll *_ep, int _fd) : ep(_ep), fd(_fd), events(0), revents(0), inEpoll(false){
}
Channel::~Channel()
{
}
void Channel::enableReading(){
events = EPOLLIN | EPOLLET;
ep->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getRevents(){
return revents;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(){
inEpoll = true;
}
// void Channel::setEvents(uint32_t _ev){
// events = _ev;
// }
void Channel::setRevents(uint32_t _ev){
revents = _ev;
}
================================================
FILE: code/day05/Channel.h
================================================
#pragma once
#include <sys/epoll.h>
class Epoll;
class Channel
{
private:
Epoll *ep;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
public:
Channel(Epoll *_ep, int _fd);
~Channel();
void enableReading();
int getFd();
uint32_t getEvents();
uint32_t getRevents();
bool getInEpoll();
void setInEpoll();
// void setEvents(uint32_t);
void setRevents(uint32_t);
};
================================================
FILE: code/day05/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
void Epoll::addFd(int fd, uint32_t op){
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.fd = fd;
ev.events = op;
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
}
// std::vector<epoll_event> Epoll::poll(int timeout){
// std::vector<epoll_event> activeEvents;
// int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
// errif(nfds == -1, "epoll wait error");
// for(int i = 0; i < nfds; ++i){
// activeEvents.push_back(events[i]);
// }
// return activeEvents;
// }
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setRevents(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
// debug("Epoll: add Channel to epoll tree success, the Channel's fd is: ", fd);
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
// debug("Epoll: modify Channel in epoll tree success, the Channel's fd is: ", fd);
}
}
================================================
FILE: code/day05/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
void addFd(int fd, uint32_t op);
void updateChannel(Channel*);
// std::vector<epoll_event> poll(int timeout = -1);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day05/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
================================================
FILE: code/day05/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
public:
struct sockaddr_in addr;
socklen_t addr_len;
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
};
================================================
FILE: code/day05/Makefile
================================================
server:
g++ util.cpp client.cpp -o client && \
g++ util.cpp server.cpp Epoll.cpp InetAddress.cpp Socket.cpp Channel.cpp -o server
clean:
rm server && rm client
================================================
FILE: code/day05/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *addr){
errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error");
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *addr){
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len);
errif(clnt_sockfd == -1, "socket accept error");
return clnt_sockfd;
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day05/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
int getFd();
};
================================================
FILE: code/day05/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么?
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day05/server.cpp
================================================
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <vector>
#include "util.h"
#include "Epoll.h"
#include "InetAddress.h"
#include "Socket.h"
#include "Channel.h"
#define MAX_EVENTS 1024
#define READ_BUFFER 1024
void setnonblocking(int fd){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
void handleReadEvent(int);
int main() {
Socket *serv_sock = new Socket();
InetAddress *serv_addr = new InetAddress("127.0.0.1", 8888);
serv_sock->bind(serv_addr);
serv_sock->listen();
Epoll *ep = new Epoll();
serv_sock->setnonblocking();
Channel *servChannel = new Channel(ep, serv_sock->getFd());
servChannel->enableReading();
while(true){
std::vector<Channel*> activeChannels = ep->poll();
int nfds = activeChannels.size();
for(int i = 0; i < nfds; ++i){
int chfd = activeChannels[i]->getFd();
if(chfd == serv_sock->getFd()){ //新客户端连接
InetAddress *clnt_addr = new InetAddress(); //会发生内存泄露!没有delete
Socket *clnt_sock = new Socket(serv_sock->accept(clnt_addr)); //会发生内存泄露!没有delete
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->addr.sin_addr), ntohs(clnt_addr->addr.sin_port));
clnt_sock->setnonblocking();
Channel *clntChannel = new Channel(ep, clnt_sock->getFd());
clntChannel->enableReading();
} else if(activeChannels[i]->getRevents() & EPOLLIN){ //可读事件
handleReadEvent(activeChannels[i]->getFd());
} else{ //其他事件,之后的版本实现
printf("something else happened\n");
}
}
}
delete serv_sock;
delete serv_addr;
return 0;
}
void handleReadEvent(int sockfd){
char buf[READ_BUFFER];
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
printf("message from client fd %d: %s\n", sockfd, buf);
write(sockfd, buf, sizeof(buf));
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once, errno: %d\n", errno);
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
break;
}
}
}
================================================
FILE: code/day05/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day05/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day06/Makefile
================================================
server:
g++ src/util.cpp client.cpp -o client && \
g++ src/util.cpp server.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Channel.cpp src/EventLoop.cpp src/Server.cpp -o server
clean:
rm server && rm client
================================================
FILE: code/day06/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "src/util.h"
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么?
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day06/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
return 0;
}
================================================
FILE: code/day06/src/Channel.cpp
================================================
#include "Channel.h"
#include "EventLoop.h"
Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){
}
Channel::~Channel()
{
}
void Channel::handleEvent(){
callback();
}
void Channel::enableReading(){
events = EPOLLIN | EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getRevents(){
return revents;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(){
inEpoll = true;
}
// void Channel::setEvents(uint32_t _ev){
// events = _ev;
// }
void Channel::setRevents(uint32_t _ev){
revents = _ev;
}
void Channel::setCallback(std::function<void()> _cb){
callback = _cb;
}
================================================
FILE: code/day06/src/Channel.h
================================================
#pragma once
#include <sys/epoll.h>
#include <functional>
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
std::function<void()> callback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableReading();
int getFd();
uint32_t getEvents();
uint32_t getRevents();
bool getInEpoll();
void setInEpoll();
// void setEvents(uint32_t);
void setRevents(uint32_t);
void setCallback(std::function<void()>);
};
================================================
FILE: code/day06/src/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
void Epoll::addFd(int fd, uint32_t op){
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.fd = fd;
ev.events = op;
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
}
// std::vector<epoll_event> Epoll::poll(int timeout){
// std::vector<epoll_event> activeEvents;
// int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
// errif(nfds == -1, "epoll wait error");
// for(int i = 0; i < nfds; ++i){
// activeEvents.push_back(events[i]);
// }
// return activeEvents;
// }
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setRevents(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
// debug("Epoll: add Channel to epoll tree success, the Channel's fd is: ", fd);
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
// debug("Epoll: modify Channel in epoll tree success, the Channel's fd is: ", fd);
}
}
================================================
FILE: code/day06/src/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
void addFd(int fd, uint32_t op);
void updateChannel(Channel*);
// std::vector<epoll_event> poll(int timeout = -1);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day06/src/EventLoop.cpp
================================================
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), quit(false){
ep = new Epoll();
}
EventLoop::~EventLoop()
{
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
================================================
FILE: code/day06/src/EventLoop.h
================================================
#pragma once
class Epoll;
class Channel;
class EventLoop
{
private:
Epoll *ep;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
};
================================================
FILE: code/day06/src/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
================================================
FILE: code/day06/src/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
public:
struct sockaddr_in addr;
socklen_t addr_len;
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
};
================================================
FILE: code/day06/src/Server.cpp
================================================
#include "Server.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
#include <functional>
#include <string.h>
#include <unistd.h>
#define READ_BUFFER 1024
Server::Server(EventLoop *_loop) : loop(_loop){
Socket *serv_sock = new Socket();
InetAddress *serv_addr = new InetAddress("127.0.0.1", 8888);
serv_sock->bind(serv_addr);
serv_sock->listen();
serv_sock->setnonblocking();
Channel *servChannel = new Channel(loop, serv_sock->getFd());
std::function<void()> cb = std::bind(&Server::newConnection, this, serv_sock);
servChannel->setCallback(cb);
servChannel->enableReading();
}
Server::~Server()
{
}
void Server::handleReadEvent(int sockfd){
char buf[READ_BUFFER];
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
printf("message from client fd %d: %s\n", sockfd, buf);
write(sockfd, buf, sizeof(buf));
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once, errno: %d\n", errno);
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
break;
}
}
}
void Server::newConnection(Socket *serv_sock){
InetAddress *clnt_addr = new InetAddress(); //会发生内存泄露!没有delete
Socket *clnt_sock = new Socket(serv_sock->accept(clnt_addr)); //会发生内存泄露!没有delete
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->addr.sin_addr), ntohs(clnt_addr->addr.sin_port));
clnt_sock->setnonblocking();
Channel *clntChannel = new Channel(loop, clnt_sock->getFd());
std::function<void()> cb = std::bind(&Server::handleReadEvent, this, clnt_sock->getFd());
clntChannel->setCallback(cb);
clntChannel->enableReading();
}
================================================
FILE: code/day06/src/Server.h
================================================
#pragma once
class EventLoop;
class Socket;
class Server
{
private:
EventLoop *loop;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *serv_sock);
};
================================================
FILE: code/day06/src/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *addr){
errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error");
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *addr){
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len);
errif(clnt_sockfd == -1, "socket accept error");
return clnt_sockfd;
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day06/src/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
int getFd();
};
================================================
FILE: code/day06/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day06/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day07/Makefile
================================================
server:
g++ src/util.cpp client.cpp -o client && \
g++ src/util.cpp server.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp -o server
clean:
rm server && rm client
================================================
FILE: code/day07/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "src/util.h"
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么?
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day07/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
return 0;
}
================================================
FILE: code/day07/src/Acceptor.cpp
================================================
#include "Acceptor.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
#include "Server.h"
Acceptor::Acceptor(EventLoop *_loop) : loop(_loop)
{
sock = new Socket();
addr = new InetAddress("127.0.0.1", 8888);
sock->bind(addr);
sock->listen();
sock->setnonblocking();
acceptChannel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Acceptor::acceptConnection, this);
acceptChannel->setCallback(cb);
acceptChannel->enableReading();
}
Acceptor::~Acceptor(){
delete sock;
delete addr;
delete acceptChannel;
}
void Acceptor::acceptConnection(){
newConnectionCallback(sock);
}
void Acceptor::setNewConnectionCallback(std::function<void(Socket*)> _cb){
newConnectionCallback = _cb;
}
================================================
FILE: code/day07/src/Acceptor.h
================================================
#pragma once
#include <functional>
class EventLoop;
class Socket;
class InetAddress;
class Channel;
class Acceptor
{
private:
EventLoop *loop;
Socket *sock;
InetAddress *addr;
Channel *acceptChannel;
public:
Acceptor(EventLoop *_loop);
~Acceptor();
void acceptConnection();
std::function<void(Socket*)> newConnectionCallback;
void setNewConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day07/src/Channel.cpp
================================================
#include "Channel.h"
#include "EventLoop.h"
Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){
}
Channel::~Channel()
{
}
void Channel::handleEvent(){
callback();
}
void Channel::enableReading(){
events |= EPOLLIN | EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getRevents(){
return revents;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(){
inEpoll = true;
}
// void Channel::setEvents(uint32_t _ev){
// events = _ev;
// }
void Channel::setRevents(uint32_t _ev){
revents = _ev;
}
void Channel::setCallback(std::function<void()> _cb){
callback = _cb;
}
================================================
FILE: code/day07/src/Channel.h
================================================
#pragma once
#include <sys/epoll.h>
#include <functional>
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
std::function<void()> callback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableReading();
int getFd();
uint32_t getEvents();
uint32_t getRevents();
bool getInEpoll();
void setInEpoll();
// void setEvents(uint32_t);
void setRevents(uint32_t);
void setCallback(std::function<void()>);
};
================================================
FILE: code/day07/src/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
void Epoll::addFd(int fd, uint32_t op){
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.fd = fd;
ev.events = op;
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
}
// std::vector<epoll_event> Epoll::poll(int timeout){
// std::vector<epoll_event> activeEvents;
// int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
// errif(nfds == -1, "epoll wait error");
// for(int i = 0; i < nfds; ++i){
// activeEvents.push_back(events[i]);
// }
// return activeEvents;
// }
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setRevents(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
// debug("Epoll: add Channel to epoll tree success, the Channel's fd is: ", fd);
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
// debug("Epoll: modify Channel in epoll tree success, the Channel's fd is: ", fd);
}
}
================================================
FILE: code/day07/src/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
void addFd(int fd, uint32_t op);
void updateChannel(Channel*);
// std::vector<epoll_event> poll(int timeout = -1);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day07/src/EventLoop.cpp
================================================
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), quit(false){
ep = new Epoll();
}
EventLoop::~EventLoop()
{
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
================================================
FILE: code/day07/src/EventLoop.h
================================================
#pragma once
class Epoll;
class Channel;
class EventLoop
{
private:
Epoll *ep;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
};
================================================
FILE: code/day07/src/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
================================================
FILE: code/day07/src/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
public:
struct sockaddr_in addr;
socklen_t addr_len;
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
};
================================================
FILE: code/day07/src/Server.cpp
================================================
#include "Server.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
#include "Acceptor.h"
#include <functional>
#include <string.h>
#include <unistd.h>
#define READ_BUFFER 1024
Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){
acceptor = new Acceptor(loop);
std::function<void(Socket*)> cb = std::bind(&Server::newConnection, this, std::placeholders::_1);
acceptor->setNewConnectionCallback(cb);
}
Server::~Server(){
delete acceptor;
}
void Server::handleReadEvent(int sockfd){
char buf[READ_BUFFER];
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
printf("message from client fd %d: %s\n", sockfd, buf);
write(sockfd, buf, sizeof(buf));
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once, errno: %d\n", errno);
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
break;
}
}
}
void Server::newConnection(Socket *serv_sock){
InetAddress *clnt_addr = new InetAddress(); //会发生内存泄露!没有delete
Socket *clnt_sock = new Socket(serv_sock->accept(clnt_addr)); //会发生内存泄露!没有delete
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->addr.sin_addr), ntohs(clnt_addr->addr.sin_port));
clnt_sock->setnonblocking();
Channel *clntChannel = new Channel(loop, clnt_sock->getFd());
std::function<void()> cb = std::bind(&Server::handleReadEvent, this, clnt_sock->getFd());
clntChannel->setCallback(cb);
clntChannel->enableReading();
}
================================================
FILE: code/day07/src/Server.h
================================================
#pragma once
class EventLoop;
class Socket;
class Acceptor;
class Server
{
private:
EventLoop *loop;
Acceptor *acceptor;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *serv_sock);
};
================================================
FILE: code/day07/src/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *addr){
errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error");
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *addr){
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len);
errif(clnt_sockfd == -1, "socket accept error");
return clnt_sockfd;
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day07/src/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
int getFd();
};
================================================
FILE: code/day07/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day07/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day08/Makefile
================================================
server:
g++ src/util.cpp client.cpp -o client && \
g++ server.cpp \
src/util.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Connection.cpp \
src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp \
-o server
clean:
rm server && rm client
================================================
FILE: code/day08/client.cpp
================================================
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include "src/util.h"
#define BUFFER_SIZE 1024
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
errif(sockfd == -1, "socket create error");
struct sockaddr_in serv_addr;
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1234);
errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error");
while(true){
char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么?
bzero(&buf, sizeof(buf));
scanf("%s", buf);
ssize_t write_bytes = write(sockfd, buf, sizeof(buf));
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
printf("message from server: %s\n", buf);
}else if(read_bytes == 0){
printf("server socket disconnected!\n");
break;
}else if(read_bytes == -1){
close(sockfd);
errif(true, "socket read error");
}
}
close(sockfd);
return 0;
}
================================================
FILE: code/day08/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
return 0;
}
================================================
FILE: code/day08/src/Acceptor.cpp
================================================
#include "Acceptor.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){
sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->bind(addr);
sock->listen();
sock->setnonblocking();
acceptChannel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Acceptor::acceptConnection, this);
acceptChannel->setCallback(cb);
acceptChannel->enableReading();
delete addr;
}
Acceptor::~Acceptor(){
delete sock;
delete acceptChannel;
}
void Acceptor::acceptConnection(){
InetAddress *clnt_addr = new InetAddress();
Socket *clnt_sock = new Socket(sock->accept(clnt_addr));
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->getAddr().sin_addr), ntohs(clnt_addr->getAddr().sin_port));
clnt_sock->setnonblocking();
newConnectionCallback(clnt_sock);
delete clnt_addr;
}
void Acceptor::setNewConnectionCallback(std::function<void(Socket*)> _cb){
newConnectionCallback = _cb;
}
================================================
FILE: code/day08/src/Acceptor.h
================================================
#pragma once
#include <functional>
class EventLoop;
class Socket;
class Channel;
class Acceptor
{
private:
EventLoop *loop;
Socket *sock;
Channel *acceptChannel;
std::function<void(Socket*)> newConnectionCallback;
public:
Acceptor(EventLoop *_loop);
~Acceptor();
void acceptConnection();
void setNewConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day08/src/Channel.cpp
================================================
#include "Channel.h"
#include "EventLoop.h"
#include <unistd.h>
Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){
}
Channel::~Channel(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Channel::handleEvent(){
callback();
}
void Channel::enableReading(){
events |= EPOLLIN | EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getRevents(){
return revents;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(){
inEpoll = true;
}
// void Channel::setEvents(uint32_t _ev){
// events = _ev;
// }
void Channel::setRevents(uint32_t _ev){
revents = _ev;
}
void Channel::setCallback(std::function<void()> _cb){
callback = _cb;
}
================================================
FILE: code/day08/src/Channel.h
================================================
#pragma once
#include <sys/epoll.h>
#include <functional>
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
std::function<void()> callback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableReading();
int getFd();
uint32_t getEvents();
uint32_t getRevents();
bool getInEpoll();
void setInEpoll();
// void setEvents(uint32_t);
void setRevents(uint32_t);
void setCallback(std::function<void()>);
};
================================================
FILE: code/day08/src/Connection.cpp
================================================
#include "Connection.h"
#include "Socket.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define READ_BUFFER 1024
Connection::Connection(EventLoop *_loop, Socket *_sock) : loop(_loop), sock(_sock), channel(nullptr){
channel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Connection::echo, this, sock->getFd());
channel->setCallback(cb);
channel->enableReading();
}
Connection::~Connection(){
delete channel;
delete sock;
}
void Connection::echo(int sockfd){
char buf[READ_BUFFER];
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
printf("message from client fd %d: %s\n", sockfd, buf);
write(sockfd, buf, sizeof(buf));
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once, errno: %d\n", errno);
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
// close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
deleteConnectionCallback(sock);
break;
}
}
}
void Connection::setDeleteConnectionCallback(std::function<void(Socket*)> _cb){
deleteConnectionCallback = _cb;
}
================================================
FILE: code/day08/src/Connection.h
================================================
#pragma once
#include <functional>
class EventLoop;
class Socket;
class Channel;
class Connection
{
private:
EventLoop *loop;
Socket *sock;
Channel *channel;
std::function<void(Socket*)> deleteConnectionCallback;
public:
Connection(EventLoop *_loop, Socket *_sock);
~Connection();
void echo(int sockfd);
void setDeleteConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day08/src/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
// void Epoll::addFd(int fd, uint32_t op){
// struct epoll_event ev;
// bzero(&ev, sizeof(ev));
// ev.data.fd = fd;
// ev.events = op;
// errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
// }
// std::vector<epoll_event> Epoll::poll(int timeout){
// std::vector<epoll_event> activeEvents;
// int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
// errif(nfds == -1, "epoll wait error");
// for(int i = 0; i < nfds; ++i){
// activeEvents.push_back(events[i]);
// }
// return activeEvents;
// }
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setRevents(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
// debug("Epoll: add Channel to epoll tree success, the Channel's fd is: ", fd);
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
// debug("Epoll: modify Channel in epoll tree success, the Channel's fd is: ", fd);
}
}
================================================
FILE: code/day08/src/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
// void addFd(int fd, uint32_t op);
void updateChannel(Channel*);
// std::vector<epoll_event> poll(int timeout = -1);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day08/src/EventLoop.cpp
================================================
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), quit(false){
ep = new Epoll();
}
EventLoop::~EventLoop()
{
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
================================================
FILE: code/day08/src/EventLoop.h
================================================
#pragma once
class Epoll;
class Channel;
class EventLoop
{
private:
Epoll *ep;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
};
================================================
FILE: code/day08/src/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
void InetAddress::setInetAddr(sockaddr_in _addr, socklen_t _addr_len){
addr = _addr;
addr_len = _addr_len;
}
sockaddr_in InetAddress::getAddr(){
return addr;
}
socklen_t InetAddress::getAddr_len(){
return addr_len;
}
================================================
FILE: code/day08/src/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
private:
struct sockaddr_in addr;
socklen_t addr_len;
public:
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
void setInetAddr(sockaddr_in _addr, socklen_t _addr_len);
sockaddr_in getAddr();
socklen_t getAddr_len();
};
================================================
FILE: code/day08/src/Server.cpp
================================================
#include "Server.h"
#include "Socket.h"
#include "Acceptor.h"
#include "Connection.h"
#include <functional>
Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){
acceptor = new Acceptor(loop);
std::function<void(Socket*)> cb = std::bind(&Server::newConnection, this, std::placeholders::_1);
acceptor->setNewConnectionCallback(cb);
}
Server::~Server(){
delete acceptor;
}
void Server::newConnection(Socket *sock){
Connection *conn = new Connection(loop, sock);
std::function<void(Socket*)> cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1);
conn->setDeleteConnectionCallback(cb);
connections[sock->getFd()] = conn;
}
void Server::deleteConnection(Socket * sock){
Connection *conn = connections[sock->getFd()];
connections.erase(sock->getFd());
delete conn;
}
================================================
FILE: code/day08/src/Server.h
================================================
#pragma once
#include <map>
class EventLoop;
class Socket;
class Acceptor;
class Connection;
class Server
{
private:
EventLoop *loop;
Acceptor *acceptor;
std::map<int, Connection*> connections;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *sock);
void deleteConnection(Socket *sock);
};
================================================
FILE: code/day08/src/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
socklen_t addr_len = _addr->getAddr_len();
errif(::bind(fd, (sockaddr*)&addr, addr_len) == -1, "socket bind error");
_addr->setInetAddr(addr, addr_len);
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *_addr){
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
bzero(&addr, sizeof(addr));
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len);
errif(clnt_sockfd == -1, "socket accept error");
_addr->setInetAddr(addr, addr_len);
return clnt_sockfd;
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day08/src/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int _fd);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
int getFd();
};
================================================
FILE: code/day08/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day08/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day09/Makefile
================================================
server:
g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client && \
g++ server.cpp \
src/util.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Connection.cpp \
src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp src/Buffer.cpp \
-o server
clean:
rm server && rm client
================================================
FILE: code/day09/client.cpp
================================================
#include <iostream>
#include <unistd.h>
#include <string.h>
#include "src/util.h"
#include "src/Buffer.h"
#include "src/InetAddress.h"
#include "src/Socket.h"
using namespace std;
int main() {
Socket *sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->connect(addr);
int sockfd = sock->getFd();
Buffer *sendBuffer = new Buffer();
Buffer *readBuffer = new Buffer();
while(true){
sendBuffer->getline();
ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size());
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
int already_read = 0;
char buf[1024]; //这个buf大小无所谓
while(true){
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
readBuffer->append(buf, read_bytes);
already_read += read_bytes;
} else if(read_bytes == 0){ //EOF
printf("server disconnected!\n");
exit(EXIT_SUCCESS);
}
if(already_read >= sendBuffer->size()){
printf("message from server: %s\n", readBuffer->c_str());
break;
}
}
readBuffer->clear();
}
delete addr;
delete sock;
return 0;
}
================================================
FILE: code/day09/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
delete server;
delete loop;
return 0;
}
================================================
FILE: code/day09/src/Acceptor.cpp
================================================
#include "Acceptor.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){
sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->bind(addr);
sock->listen();
sock->setnonblocking();
acceptChannel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Acceptor::acceptConnection, this);
acceptChannel->setCallback(cb);
acceptChannel->enableReading();
delete addr;
}
Acceptor::~Acceptor(){
delete sock;
delete acceptChannel;
}
void Acceptor::acceptConnection(){
InetAddress *clnt_addr = new InetAddress();
Socket *clnt_sock = new Socket(sock->accept(clnt_addr));
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->getAddr().sin_addr), ntohs(clnt_addr->getAddr().sin_port));
clnt_sock->setnonblocking();
newConnectionCallback(clnt_sock);
delete clnt_addr;
}
void Acceptor::setNewConnectionCallback(std::function<void(Socket*)> _cb){
newConnectionCallback = _cb;
}
================================================
FILE: code/day09/src/Acceptor.h
================================================
#pragma once
#include <functional>
class EventLoop;
class Socket;
class Channel;
class Acceptor
{
private:
EventLoop *loop;
Socket *sock;
Channel *acceptChannel;
std::function<void(Socket*)> newConnectionCallback;
public:
Acceptor(EventLoop *_loop);
~Acceptor();
void acceptConnection();
void setNewConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day09/src/Buffer.cpp
================================================
#include "Buffer.h"
#include <string.h>
#include <iostream>
Buffer::Buffer()
{
}
Buffer::~Buffer()
{
}
void Buffer::append(const char* _str, int _size){
for(int i = 0; i < _size; ++i){
if(_str[i] == '\0') break;
buf.push_back(_str[i]);
}
}
ssize_t Buffer::size(){
return buf.size();
}
const char* Buffer::c_str(){
return buf.c_str();
}
void Buffer::clear(){
buf.clear();
}
void Buffer::getline(){
buf.clear();
std::getline(std::cin, buf);
}
================================================
FILE: code/day09/src/Buffer.h
================================================
#pragma once
#include <string>
class Buffer
{
private:
std::string buf;
public:
Buffer();
~Buffer();
void append(const char* _str, int _size);
ssize_t size();
const char* c_str();
void clear();
void getline();
};
================================================
FILE: code/day09/src/Channel.cpp
================================================
#include "Channel.h"
#include "EventLoop.h"
#include <unistd.h>
Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){
}
Channel::~Channel(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Channel::handleEvent(){
callback();
}
void Channel::enableReading(){
events |= EPOLLIN | EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getRevents(){
return revents;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(){
inEpoll = true;
}
// void Channel::setEvents(uint32_t _ev){
// events = _ev;
// }
void Channel::setRevents(uint32_t _ev){
revents = _ev;
}
void Channel::setCallback(std::function<void()> _cb){
callback = _cb;
}
================================================
FILE: code/day09/src/Channel.h
================================================
#pragma once
#include <sys/epoll.h>
#include <functional>
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
std::function<void()> callback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableReading();
int getFd();
uint32_t getEvents();
uint32_t getRevents();
bool getInEpoll();
void setInEpoll();
// void setEvents(uint32_t);
void setRevents(uint32_t);
void setCallback(std::function<void()>);
};
================================================
FILE: code/day09/src/Connection.cpp
================================================
#include "Connection.h"
#include "Socket.h"
#include "Channel.h"
#include "util.h"
#include "Buffer.h"
#include <unistd.h>
#include <string.h>
#include <iostream>
Connection::Connection(EventLoop *_loop, Socket *_sock) : loop(_loop), sock(_sock), channel(nullptr), inBuffer(new std::string()), readBuffer(nullptr){
channel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Connection::echo, this, sock->getFd());
channel->setCallback(cb);
channel->enableReading();
readBuffer = new Buffer();
}
Connection::~Connection(){
delete channel;
delete sock;
}
void Connection::echo(int sockfd){
char buf[1024]; //这个buf大小无所谓
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
readBuffer->append(buf, bytes_read);
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once\n");
printf("message from client fd %d: %s\n", sockfd, readBuffer->c_str());
errif(write(sockfd, readBuffer->c_str(), readBuffer->size()) == -1, "socket write error");
readBuffer->clear();
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
// close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
deleteConnectionCallback(sock);
break;
}
}
}
void Connection::setDeleteConnectionCallback(std::function<void(Socket*)> _cb){
deleteConnectionCallback = _cb;
}
================================================
FILE: code/day09/src/Connection.h
================================================
#pragma once
#include <functional>
#include <string>
class EventLoop;
class Socket;
class Channel;
class Buffer;
class Connection
{
private:
EventLoop *loop;
Socket *sock;
Channel *channel;
std::function<void(Socket*)> deleteConnectionCallback;
std::string *inBuffer;
Buffer *readBuffer;
public:
Connection(EventLoop *_loop, Socket *_sock);
~Connection();
void echo(int sockfd);
void setDeleteConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day09/src/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
// void Epoll::addFd(int fd, uint32_t op){
// struct epoll_event ev;
// bzero(&ev, sizeof(ev));
// ev.data.fd = fd;
// ev.events = op;
// errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
// }
// std::vector<epoll_event> Epoll::poll(int timeout){
// std::vector<epoll_event> activeEvents;
// int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
// errif(nfds == -1, "epoll wait error");
// for(int i = 0; i < nfds; ++i){
// activeEvents.push_back(events[i]);
// }
// return activeEvents;
// }
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setRevents(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
// debug("Epoll: add Channel to epoll tree success, the Channel's fd is: ", fd);
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
// debug("Epoll: modify Channel in epoll tree success, the Channel's fd is: ", fd);
}
}
================================================
FILE: code/day09/src/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
// void addFd(int fd, uint32_t op);
void updateChannel(Channel*);
// std::vector<epoll_event> poll(int timeout = -1);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day09/src/EventLoop.cpp
================================================
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), quit(false){
ep = new Epoll();
}
EventLoop::~EventLoop(){
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
================================================
FILE: code/day09/src/EventLoop.h
================================================
#pragma once
class Epoll;
class Channel;
class EventLoop
{
private:
Epoll *ep;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
};
================================================
FILE: code/day09/src/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
void InetAddress::setInetAddr(sockaddr_in _addr, socklen_t _addr_len){
addr = _addr;
addr_len = _addr_len;
}
sockaddr_in InetAddress::getAddr(){
return addr;
}
socklen_t InetAddress::getAddr_len(){
return addr_len;
}
================================================
FILE: code/day09/src/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
private:
struct sockaddr_in addr;
socklen_t addr_len;
public:
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
void setInetAddr(sockaddr_in _addr, socklen_t _addr_len);
sockaddr_in getAddr();
socklen_t getAddr_len();
};
================================================
FILE: code/day09/src/Server.cpp
================================================
#include "Server.h"
#include "Socket.h"
#include "Acceptor.h"
#include "Connection.h"
#include <functional>
Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){
acceptor = new Acceptor(loop);
std::function<void(Socket*)> cb = std::bind(&Server::newConnection, this, std::placeholders::_1);
acceptor->setNewConnectionCallback(cb);
}
Server::~Server(){
delete acceptor;
}
void Server::newConnection(Socket *sock){
Connection *conn = new Connection(loop, sock);
std::function<void(Socket*)> cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1);
conn->setDeleteConnectionCallback(cb);
connections[sock->getFd()] = conn;
}
void Server::deleteConnection(Socket *sock){
Connection *conn = connections[sock->getFd()];
connections.erase(sock->getFd());
delete conn;
}
================================================
FILE: code/day09/src/Server.h
================================================
#pragma once
#include <map>
class EventLoop;
class Socket;
class Acceptor;
class Connection;
class Server
{
private:
EventLoop *loop;
Acceptor *acceptor;
std::map<int, Connection*> connections;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *sock);
void deleteConnection(Socket *sock);
};
================================================
FILE: code/day09/src/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
socklen_t addr_len = _addr->getAddr_len();
errif(::bind(fd, (sockaddr*)&addr, addr_len) == -1, "socket bind error");
_addr->setInetAddr(addr, addr_len);
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *_addr){
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
bzero(&addr, sizeof(addr));
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len);
errif(clnt_sockfd == -1, "socket accept error");
_addr->setInetAddr(addr, addr_len);
return clnt_sockfd;
}
void Socket::connect(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
socklen_t addr_len = _addr->getAddr_len();
errif(::connect(fd, (sockaddr*)&addr, addr_len) == -1, "socket connect error");
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day09/src/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int _fd);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
void connect(InetAddress*);
int getFd();
};
================================================
FILE: code/day09/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day09/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day10/Makefile
================================================
server:
g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client && \
g++ server.cpp \
-pthread \
src/util.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Connection.cpp \
src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp src/Buffer.cpp \
src/ThreadPool.cpp \
-o server
clean:
rm server && rm client
threadTest:
g++ -pthread src/ThreadPool.cpp ThreadPoolTest.cpp -o ThreadPoolTest
================================================
FILE: code/day10/ThreadPoolTest.cpp
================================================
#include <iostream>
#include <string>
#include "src/ThreadPool.h"
void print(int a, double b, const char *c, std::string d){
std::cout << a << b << c << d << std::endl;
}
void test(){
std::cout << "hellp" << std::endl;
}
int main(int argc, char const *argv[])
{
ThreadPool *poll = new ThreadPool();
std::function<void()> func = std::bind(print, 1, 3.14, "hello", std::string("world"));
poll->add(func);
func = test;
poll->add(func);
delete poll;
return 0;
}
================================================
FILE: code/day10/client.cpp
================================================
#include <iostream>
#include <unistd.h>
#include <string.h>
#include "src/util.h"
#include "src/Buffer.h"
#include "src/InetAddress.h"
#include "src/Socket.h"
using namespace std;
int main() {
Socket *sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->connect(addr);
int sockfd = sock->getFd();
Buffer *sendBuffer = new Buffer();
Buffer *readBuffer = new Buffer();
while(true){
sendBuffer->getline();
ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size());
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
int already_read = 0;
char buf[1024]; //这个buf大小无所谓
while(true){
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
readBuffer->append(buf, read_bytes);
already_read += read_bytes;
} else if(read_bytes == 0){ //EOF
printf("server disconnected!\n");
exit(EXIT_SUCCESS);
}
if(already_read >= sendBuffer->size()){
printf("message from server: %s\n", readBuffer->c_str());
break;
}
}
readBuffer->clear();
}
delete addr;
delete sock;
return 0;
}
================================================
FILE: code/day10/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
delete server;
delete loop;
return 0;
}
================================================
FILE: code/day10/src/Acceptor.cpp
================================================
#include "Acceptor.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){
sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->bind(addr);
sock->listen();
sock->setnonblocking();
acceptChannel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Acceptor::acceptConnection, this);
acceptChannel->setCallback(cb);
acceptChannel->enableReading();
delete addr;
}
Acceptor::~Acceptor(){
delete sock;
delete acceptChannel;
}
void Acceptor::acceptConnection(){
InetAddress *clnt_addr = new InetAddress();
Socket *clnt_sock = new Socket(sock->accept(clnt_addr));
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->getAddr().sin_addr), ntohs(clnt_addr->getAddr().sin_port));
clnt_sock->setnonblocking();
newConnectionCallback(clnt_sock);
delete clnt_addr;
}
void Acceptor::setNewConnectionCallback(std::function<void(Socket*)> _cb){
newConnectionCallback = _cb;
}
================================================
FILE: code/day10/src/Acceptor.h
================================================
#pragma once
#include <functional>
#include <cstdio>
class EventLoop;
class Socket;
class Channel;
class Acceptor
{
private:
EventLoop *loop;
Socket *sock;
Channel *acceptChannel;
std::function<void(Socket*)> newConnectionCallback;
public:
Acceptor(EventLoop *_loop);
~Acceptor();
void acceptConnection();
void setNewConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day10/src/Buffer.cpp
================================================
#include "Buffer.h"
#include <string.h>
#include <iostream>
Buffer::Buffer()
{
}
Buffer::~Buffer()
{
}
void Buffer::append(const char* _str, int _size){
for(int i = 0; i < _size; ++i){
if(_str[i] == '\0') break;
buf.push_back(_str[i]);
}
}
ssize_t Buffer::size(){
return buf.size();
}
const char* Buffer::c_str(){
return buf.c_str();
}
void Buffer::clear(){
buf.clear();
}
void Buffer::getline(){
buf.clear();
std::getline(std::cin, buf);
}
================================================
FILE: code/day10/src/Buffer.h
================================================
#pragma once
#include <string>
class Buffer
{
private:
std::string buf;
public:
Buffer();
~Buffer();
void append(const char* _str, int _size);
ssize_t size();
const char* c_str();
void clear();
void getline();
};
================================================
FILE: code/day10/src/Channel.cpp
================================================
#include "Channel.h"
#include "EventLoop.h"
#include <unistd.h>
Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){
}
Channel::~Channel(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Channel::handleEvent(){
loop->addThread(callback);
// callback();
}
void Channel::enableReading(){
events |= EPOLLIN | EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getRevents(){
return revents;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(){
inEpoll = true;
}
// void Channel::setEvents(uint32_t _ev){
// events = _ev;
// }
void Channel::setRevents(uint32_t _ev){
revents = _ev;
}
void Channel::setCallback(std::function<void()> _cb){
callback = _cb;
}
================================================
FILE: code/day10/src/Channel.h
================================================
#pragma once
#include <sys/epoll.h>
#include <functional>
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
std::function<void()> callback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableReading();
int getFd();
uint32_t getEvents();
uint32_t getRevents();
bool getInEpoll();
void setInEpoll();
// void setEvents(uint32_t);
void setRevents(uint32_t);
void setCallback(std::function<void()>);
};
================================================
FILE: code/day10/src/Connection.cpp
================================================
#include "Connection.h"
#include "Socket.h"
#include "Channel.h"
#include "util.h"
#include "Buffer.h"
#include <unistd.h>
#include <string.h>
#include <iostream>
Connection::Connection(EventLoop *_loop, Socket *_sock) : loop(_loop), sock(_sock), channel(nullptr), inBuffer(new std::string()), readBuffer(nullptr){
channel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Connection::echo, this, sock->getFd());
channel->setCallback(cb);
channel->enableReading();
readBuffer = new Buffer();
}
Connection::~Connection(){
delete channel;
delete sock;
}
void Connection::echo(int sockfd){
char buf[1024]; //这个buf大小无所谓
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
readBuffer->append(buf, bytes_read);
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("finish reading once\n");
printf("message from client fd %d: %s\n", sockfd, readBuffer->c_str());
errif(write(sockfd, readBuffer->c_str(), readBuffer->size()) == -1, "socket write error");
readBuffer->clear();
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
// close(sockfd); //关闭socket会自动将文件描述符从epoll树上移除
deleteConnectionCallback(sock);
break;
}
}
}
void Connection::setDeleteConnectionCallback(std::function<void(Socket*)> _cb){
deleteConnectionCallback = _cb;
}
================================================
FILE: code/day10/src/Connection.h
================================================
#pragma once
#include <functional>
#include <string>
class EventLoop;
class Socket;
class Channel;
class Buffer;
class Connection
{
private:
EventLoop *loop;
Socket *sock;
Channel *channel;
std::function<void(Socket*)> deleteConnectionCallback;
std::string *inBuffer;
Buffer *readBuffer;
public:
Connection(EventLoop *_loop, Socket *_sock);
~Connection();
void echo(int sockfd);
void setDeleteConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day10/src/Epoll.cpp
================================================
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
// void Epoll::addFd(int fd, uint32_t op){
// struct epoll_event ev;
// bzero(&ev, sizeof(ev));
// ev.data.fd = fd;
// ev.events = op;
// errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error");
// }
// std::vector<epoll_event> Epoll::poll(int timeout){
// std::vector<epoll_event> activeEvents;
// int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
// errif(nfds == -1, "epoll wait error");
// for(int i = 0; i < nfds; ++i){
// activeEvents.push_back(events[i]);
// }
// return activeEvents;
// }
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setRevents(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
// debug("Epoll: add Channel to epoll tree success, the Channel's fd is: ", fd);
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
// debug("Epoll: modify Channel in epoll tree success, the Channel's fd is: ", fd);
}
}
================================================
FILE: code/day10/src/Epoll.h
================================================
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
// void addFd(int fd, uint32_t op);
void updateChannel(Channel*);
// std::vector<epoll_event> poll(int timeout = -1);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day10/src/EventLoop.cpp
================================================
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include "ThreadPool.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), threadPool(nullptr), quit(false){
ep = new Epoll();
threadPool = new ThreadPool();
}
EventLoop::~EventLoop(){
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
void EventLoop::addThread(std::function<void()> func){
threadPool->add(func);
}
================================================
FILE: code/day10/src/EventLoop.h
================================================
#pragma once
#include <functional>
class Epoll;
class Channel;
class ThreadPool;
class EventLoop
{
private:
Epoll *ep;
ThreadPool *threadPool;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
void addThread(std::function<void()>);
};
================================================
FILE: code/day10/src/InetAddress.cpp
================================================
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
addr_len = sizeof(addr);
}
InetAddress::~InetAddress(){
}
void InetAddress::setInetAddr(sockaddr_in _addr, socklen_t _addr_len){
addr = _addr;
addr_len = _addr_len;
}
sockaddr_in InetAddress::getAddr(){
return addr;
}
socklen_t InetAddress::getAddr_len(){
return addr_len;
}
================================================
FILE: code/day10/src/InetAddress.h
================================================
#pragma once
#include <arpa/inet.h>
class InetAddress
{
private:
struct sockaddr_in addr;
socklen_t addr_len;
public:
InetAddress();
InetAddress(const char* ip, uint16_t port);
~InetAddress();
void setInetAddr(sockaddr_in _addr, socklen_t _addr_len);
sockaddr_in getAddr();
socklen_t getAddr_len();
};
================================================
FILE: code/day10/src/Server.cpp
================================================
#include "Server.h"
#include "Socket.h"
#include "Acceptor.h"
#include "Connection.h"
#include <functional>
Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){
acceptor = new Acceptor(loop);
std::function<void(Socket*)> cb = std::bind(&Server::newConnection, this, std::placeholders::_1);
acceptor->setNewConnectionCallback(cb);
}
Server::~Server(){
delete acceptor;
}
void Server::newConnection(Socket *sock){
Connection *conn = new Connection(loop, sock);
std::function<void(Socket*)> cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1);
conn->setDeleteConnectionCallback(cb);
connections[sock->getFd()] = conn;
}
void Server::deleteConnection(Socket *sock){
Connection *conn = connections[sock->getFd()];
connections.erase(sock->getFd());
delete conn;
}
================================================
FILE: code/day10/src/Server.h
================================================
#pragma once
#include <map>
class EventLoop;
class Socket;
class Acceptor;
class Connection;
class Server
{
private:
EventLoop *loop;
Acceptor *acceptor;
std::map<int, Connection*> connections;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *sock);
void deleteConnection(Socket *sock);
};
================================================
FILE: code/day10/src/Socket.cpp
================================================
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
socklen_t addr_len = _addr->getAddr_len();
errif(::bind(fd, (sockaddr*)&addr, addr_len) == -1, "socket bind error");
_addr->setInetAddr(addr, addr_len);
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *_addr){
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
bzero(&addr, sizeof(addr));
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len);
errif(clnt_sockfd == -1, "socket accept error");
_addr->setInetAddr(addr, addr_len);
return clnt_sockfd;
}
void Socket::connect(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
socklen_t addr_len = _addr->getAddr_len();
errif(::connect(fd, (sockaddr*)&addr, addr_len) == -1, "socket connect error");
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day10/src/Socket.h
================================================
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int _fd);
~Socket();
void bind(InetAddress*);
void listen();
void setnonblocking();
int accept(InetAddress*);
void connect(InetAddress*);
int getFd();
};
================================================
FILE: code/day10/src/ThreadPool.cpp
================================================
#include "ThreadPool.h"
ThreadPool::ThreadPool(int size) : stop(false){
for(int i = 0; i < size; ++i){
threads.emplace_back(std::thread([this](){
while(true){
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(tasks_mtx);
cv.wait(lock, [this](){
return stop || !tasks.empty();
});
if(stop && tasks.empty()) return;
task = tasks.front();
tasks.pop();
}
task();
}
}));
}
}
ThreadPool::~ThreadPool(){
{
std::unique_lock<std::mutex> lock(tasks_mtx);
stop = true;
}
cv.notify_all();
for(std::thread &th : threads){
if(th.joinable())
th.join();
}
}
void ThreadPool::add(std::function<void()> func){
{
std::unique_lock<std::mutex> lock(tasks_mtx);
if(stop)
throw std::runtime_error("ThreadPool already stop, can't add task any more");
tasks.emplace(func);
}
cv.notify_one();
}
================================================
FILE: code/day10/src/ThreadPool.h
================================================
#pragma once
#include <functional>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
class ThreadPool
{
private:
std::vector<std::thread> threads;
std::queue<std::function<void()>> tasks;
std::mutex tasks_mtx;
std::condition_variable cv;
bool stop;
public:
ThreadPool(int size = 10);
~ThreadPool();
void add(std::function<void()>);
};
================================================
FILE: code/day10/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day10/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day11/.vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/server",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
================================================
FILE: code/day11/Makefile
================================================
src=$(wildcard src/*.cpp)
server:
g++ -std=c++11 -pthread -g \
$(src) \
server.cpp \
-o server
client:
g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client
th:
g++ -pthread src/ThreadPool.cpp ThreadPoolTest.cpp -o ThreadPoolTest
test:
g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp src/ThreadPool.cpp \
-pthread \
test.cpp -o test
clean:
rm server && rm client && rm test
================================================
FILE: code/day11/ThreadPoolTest.cpp
================================================
#include <iostream>
#include <string>
#include "src/ThreadPool.h"
void print(int a, double b, const char *c, std::string d){
std::cout << a << b << c << d << std::endl;
}
void test(){
std::cout << "hellp" << std::endl;
}
int main(int argc, char const *argv[])
{
ThreadPool *poll = new ThreadPool();
std::function<void()> func = std::bind(print, 1, 3.14, "hello", std::string("world"));
poll->add(func);
func = test;
poll->add(func);
delete poll;
return 0;
}
================================================
FILE: code/day11/client.cpp
================================================
#include <iostream>
#include <unistd.h>
#include <string.h>
#include "src/util.h"
#include "src/Buffer.h"
#include "src/InetAddress.h"
#include "src/Socket.h"
using namespace std;
int main() {
Socket *sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->connect(addr);
int sockfd = sock->getFd();
Buffer *sendBuffer = new Buffer();
Buffer *readBuffer = new Buffer();
while(true){
sendBuffer->getline();
ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size());
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
int already_read = 0;
char buf[1024]; //这个buf大小无所谓
while(true){
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
readBuffer->append(buf, read_bytes);
already_read += read_bytes;
} else if(read_bytes == 0){ //EOF
printf("server disconnected!\n");
exit(EXIT_SUCCESS);
}
if(already_read >= sendBuffer->size()){
printf("message from server: %s\n", readBuffer->c_str());
break;
}
}
readBuffer->clear();
}
delete addr;
delete sock;
return 0;
}
================================================
FILE: code/day11/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
return 0;
}
================================================
FILE: code/day11/src/Acceptor.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Acceptor.h"
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){
sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->bind(addr);
// sock->setnonblocking();
sock->listen();
acceptChannel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Acceptor::acceptConnection, this);
acceptChannel->setReadCallback(cb);
acceptChannel->enableRead();
acceptChannel->setUseThreadPool(false);
delete addr;
}
Acceptor::~Acceptor(){
delete sock;
delete acceptChannel;
}
void Acceptor::acceptConnection(){
InetAddress *clnt_addr = new InetAddress();
Socket *clnt_sock = new Socket(sock->accept(clnt_addr));
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), inet_ntoa(clnt_addr->getAddr().sin_addr), ntohs(clnt_addr->getAddr().sin_port));
clnt_sock->setnonblocking();
newConnectionCallback(clnt_sock);
delete clnt_addr;
}
void Acceptor::setNewConnectionCallback(std::function<void(Socket*)> _cb){
newConnectionCallback = _cb;
}
================================================
FILE: code/day11/src/Acceptor.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class EventLoop;
class Socket;
class Channel;
class Acceptor
{
private:
EventLoop *loop;
Socket *sock;
Channel *acceptChannel;
std::function<void(Socket*)> newConnectionCallback;
public:
Acceptor(EventLoop *_loop);
~Acceptor();
void acceptConnection();
void setNewConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day11/src/Buffer.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Buffer.h"
#include <string.h>
#include <iostream>
Buffer::Buffer() {}
Buffer::~Buffer() {}
void Buffer::append(const char* _str, int _size){
for(int i = 0; i < _size; ++i){
if(_str[i] == '\0') break;
buf.push_back(_str[i]);
}
}
ssize_t Buffer::size(){
return buf.size();
}
const char* Buffer::c_str(){
return buf.c_str();
}
void Buffer::clear(){
buf.clear();
}
void Buffer::getline(){
buf.clear();
std::getline(std::cin, buf);
}
void Buffer::setBuf(const char* _buf){
buf.clear();
buf.append(_buf);
}
================================================
FILE: code/day11/src/Buffer.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <string>
class Buffer
{
private:
std::string buf;
public:
Buffer();
~Buffer();
void append(const char* _str, int _size);
ssize_t size();
const char* c_str();
void clear();
void getline();
void setBuf(const char*);
};
================================================
FILE: code/day11/src/Channel.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Channel.h"
#include "EventLoop.h"
#include "Socket.h"
#include <unistd.h>
#include <sys/epoll.h>
Channel::Channel(EventLoop *_loop, int _fd)
: loop(_loop), fd(_fd), events(0), ready(0), inEpoll(false), useThreadPool(true){}
Channel::~Channel(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Channel::handleEvent(){
if(ready & (EPOLLIN | EPOLLPRI)){
if(useThreadPool)
loop->addThread(readCallback);
else
readCallback();
}
if(ready & (EPOLLOUT)){
if(useThreadPool)
loop->addThread(writeCallback);
else
writeCallback();
}
}
void Channel::enableRead(){
events |= EPOLLIN | EPOLLPRI;
loop->updateChannel(this);
}
void Channel::useET(){
events |= EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getReady(){
return ready;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(bool _in){
inEpoll = _in;
}
void Channel::setReady(uint32_t _ev){
ready = _ev;
}
void Channel::setReadCallback(std::function<void()> _cb){
readCallback = _cb;
}
void Channel::setUseThreadPool(bool use){
useThreadPool = use;
}
================================================
FILE: code/day11/src/Channel.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class Socket;
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t ready;
bool inEpoll;
bool useThreadPool;
std::function<void()> readCallback;
std::function<void()> writeCallback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableRead();
int getFd();
uint32_t getEvents();
uint32_t getReady();
bool getInEpoll();
void setInEpoll(bool _in = true);
void useET();
void setReady(uint32_t);
void setReadCallback(std::function<void()>);
void setUseThreadPool(bool use = true);
};
================================================
FILE: code/day11/src/Connection.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Connection.h"
#include "Socket.h"
#include "Channel.h"
#include "util.h"
#include "Buffer.h"
#include <unistd.h>
#include <string.h>
#include <iostream>
Connection::Connection(EventLoop *_loop, Socket *_sock) : loop(_loop), sock(_sock), channel(nullptr), inBuffer(new std::string()), readBuffer(nullptr){
channel = new Channel(loop, sock->getFd());
channel->enableRead();
channel->useET();
std::function<void()> cb = std::bind(&Connection::echo, this, sock->getFd());
channel->setReadCallback(cb);
channel->setUseThreadPool(true);
readBuffer = new Buffer();
}
Connection::~Connection(){
delete channel;
delete sock;
delete readBuffer;
}
void Connection::setDeleteConnectionCallback(std::function<void(int)> _cb){
deleteConnectionCallback = _cb;
}
void Connection::echo(int sockfd){
char buf[1024]; //这个buf大小无所谓
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
readBuffer->append(buf, bytes_read);
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading\n");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("message from client fd %d: %s\n", sockfd, readBuffer->c_str());
// errif(write(sockfd, readBuffer->c_str(), readBuffer->size()) == -1, "socket write error");
send(sockfd);
readBuffer->clear();
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
deleteConnectionCallback(sockfd); //多线程会有bug
break;
} else {
printf("Connection reset by peer\n");
deleteConnectionCallback(sockfd); //会有bug,注释后单线程无bug
break;
}
}
}
void Connection::send(int sockfd){
char buf[readBuffer->size()];
strcpy(buf, readBuffer->c_str());
int data_size = readBuffer->size();
int data_left = data_size;
while (data_left > 0)
{
ssize_t bytes_write = write(sockfd, buf + data_size - data_left, data_left);
if (bytes_write == -1 && errno == EAGAIN) {
break;
}
data_left -= bytes_write;
}
}
================================================
FILE: code/day11/src/Connection.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
#include <string>
class EventLoop;
class Socket;
class Channel;
class Buffer;
class Connection
{
private:
EventLoop *loop;
Socket *sock;
Channel *channel;
std::function<void(int)> deleteConnectionCallback;
std::string *inBuffer;
Buffer *readBuffer;
public:
Connection(EventLoop *_loop, Socket *_sock);
~Connection();
void echo(int sockfd);
void setDeleteConnectionCallback(std::function<void(int)>);
void send(int sockfd);
};
================================================
FILE: code/day11/src/Epoll.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setReady(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
}
}
void Epoll::deleteChannel(Channel *channel){
int fd = channel->getFd();
errif(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) == -1, "epoll delete error");
channel->setInEpoll(false);
}
================================================
FILE: code/day11/src/Epoll.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
void updateChannel(Channel*);
void deleteChannel(Channel*);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day11/src/EventLoop.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include "ThreadPool.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), threadPool(nullptr), quit(false){
ep = new Epoll();
threadPool = new ThreadPool();
}
EventLoop::~EventLoop(){
delete threadPool;
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
void EventLoop::addThread(std::function<void()> func){
threadPool->add(func);
}
================================================
FILE: code/day11/src/EventLoop.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class Epoll;
class Channel;
class ThreadPool;
class EventLoop
{
private:
Epoll *ep;
ThreadPool *threadPool;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
void addThread(std::function<void()>);
};
================================================
FILE: code/day11/src/InetAddress.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "InetAddress.h"
#include <string.h>
InetAddress::InetAddress() {
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* _ip, uint16_t _port) {
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(_ip);
addr.sin_port = htons(_port);
}
InetAddress::~InetAddress(){
}
void InetAddress::setInetAddr(sockaddr_in _addr){
addr = _addr;
}
sockaddr_in InetAddress::getAddr(){
return addr;
}
================================================
FILE: code/day11/src/InetAddress.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <arpa/inet.h>
class InetAddress
{
private:
struct sockaddr_in addr;
public:
InetAddress();
InetAddress(const char* _ip, uint16_t _port);
~InetAddress();
void setInetAddr(sockaddr_in _addr);
sockaddr_in getAddr();
};
================================================
FILE: code/day11/src/Server.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Server.h"
#include "Socket.h"
#include "Acceptor.h"
#include "Connection.h"
#include <unistd.h>
#include <functional>
Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){
acceptor = new Acceptor(loop);
std::function<void(Socket*)> cb = std::bind(&Server::newConnection, this, std::placeholders::_1);
acceptor->setNewConnectionCallback(cb);
}
Server::~Server(){
delete acceptor;
}
void Server::newConnection(Socket *sock){
if(sock->getFd() != -1){
Connection *conn = new Connection(loop, sock);
std::function<void(int)> cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1);
conn->setDeleteConnectionCallback(cb);
connections[sock->getFd()] = conn;
}
}
void Server::deleteConnection(int sockfd){
if(sockfd != -1){
auto it = connections.find(sockfd);
if(it != connections.end()){
Connection *conn = connections[sockfd];
connections.erase(sockfd);
// close(sockfd); //正常
delete conn; //会Segmant fault
}
}
}
================================================
FILE: code/day11/src/Server.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <map>
class EventLoop;
class Socket;
class Acceptor;
class Connection;
class Server
{
private:
EventLoop *loop;
Acceptor *acceptor;
std::map<int, Connection*> connections;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *sock);
void deleteConnection(int sockfd);
};
================================================
FILE: code/day11/src/Socket.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Socket.h"
#include "InetAddress.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
errif(::bind(fd, (sockaddr*)&addr, sizeof(addr)) == -1, "socket bind error");
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *_addr){
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
socklen_t addr_len = sizeof(addr);
int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len);
errif(clnt_sockfd == -1, "socket accept error");
_addr->setInetAddr(addr);
return clnt_sockfd;
}
void Socket::connect(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
errif(::connect(fd, (sockaddr*)&addr, sizeof(addr)) == -1, "socket connect error");
}
int Socket::getFd(){
return fd;
}
================================================
FILE: code/day11/src/Socket.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
class InetAddress;
class Socket
{
private:
int fd;
public:
Socket();
Socket(int _fd);
~Socket();
void bind(InetAddress*);
void listen();
int accept(InetAddress*);
void connect(InetAddress*);
void setnonblocking();
int getFd();
};
================================================
FILE: code/day11/src/ThreadPool.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "ThreadPool.h"
ThreadPool::ThreadPool(int size) : stop(false){
for(int i = 0; i < size; ++i){
threads.emplace_back(std::thread([this](){
while(true){
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(tasks_mtx);
cv.wait(lock, [this](){
return stop || !tasks.empty();
});
if(stop && tasks.empty()) return;
task = tasks.front();
tasks.pop();
}
task();
}
}));
}
}
ThreadPool::~ThreadPool(){
{
std::unique_lock<std::mutex> lock(tasks_mtx);
stop = true;
}
cv.notify_all();
for(std::thread &th : threads){
if(th.joinable())
th.join();
}
}
================================================
FILE: code/day11/src/ThreadPool.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
class ThreadPool
{
private:
std::vector<std::thread> threads;
std::queue<std::function<void()>> tasks;
std::mutex tasks_mtx;
std::condition_variable cv;
bool stop;
public:
ThreadPool(int size = 10);
~ThreadPool();
// void add(std::function<void()>);
template<class F, class... Args>
auto add(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;
};
//不能放在cpp文件,原因是C++编译器不支持模版的分离编译
template<class F, class... Args>
auto ThreadPool::add(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(tasks_mtx);
// don't allow enqueueing after stopping the pool
if(stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task](){ (*task)(); });
}
cv.notify_one();
return res;
}
================================================
FILE: code/day11/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day11/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day11/test.cpp
================================================
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <functional>
#include "src/util.h"
#include "src/Buffer.h"
#include "src/InetAddress.h"
#include "src/Socket.h"
#include "src/ThreadPool.h"
using namespace std;
void oneClient(int msgs, int wait){
Socket *sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->connect(addr);
int sockfd = sock->getFd();
Buffer *sendBuffer = new Buffer();
Buffer *readBuffer = new Buffer();
sleep(wait);
int count = 0;
while(count < msgs){
sendBuffer->setBuf("I'm client!");
ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size());
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
int already_read = 0;
char buf[1024]; //这个buf大小无所谓
while(true){
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
readBuffer->append(buf, read_bytes);
already_read += read_bytes;
} else if(read_bytes == 0){ //EOF
printf("server disconnected!\n");
exit(EXIT_SUCCESS);
}
if(already_read >= sendBuffer->size()){
printf("count: %d, message from server: %s\n", count++, readBuffer->c_str());
break;
}
}
readBuffer->clear();
}
delete addr;
delete sock;
}
int main(int argc, char *argv[]) {
int threads = 100;
int msgs = 100;
int wait = 0;
int o;
const char *optstring = "t:m:w:";
while ((o = getopt(argc, argv, optstring)) != -1) {
switch (o) {
case 't':
threads = stoi(optarg);
break;
case 'm':
msgs = stoi(optarg);
break;
case 'w':
wait = stoi(optarg);
break;
case '?':
printf("error optopt: %c\n", optopt);
printf("error opterr: %d\n", opterr);
break;
}
}
ThreadPool *poll = new ThreadPool(threads);
std::function<void()> func = std::bind(oneClient, msgs, wait);
for(int i = 0; i < threads; ++i){
poll->add(func);
}
delete poll;
return 0;
}
================================================
FILE: code/day12/.vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/server",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
================================================
FILE: code/day12/Makefile
================================================
src=$(wildcard src/*.cpp)
server:
g++ -std=c++11 -pthread -g \
$(src) \
server.cpp \
-o server
client:
g++ src/util.cpp src/Buffer.cpp src/Socket.cpp client.cpp -o client
th:
g++ -pthread src/ThreadPool.cpp ThreadPoolTest.cpp -o ThreadPoolTest
test:
g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/ThreadPool.cpp \
-pthread \
test.cpp -o test
clean:
rm server && rm client && rm test
================================================
FILE: code/day12/ThreadPoolTest.cpp
================================================
#include <iostream>
#include <string>
#include "src/ThreadPool.h"
void print(int a, double b, const char *c, std::string d){
std::cout << a << b << c << d << std::endl;
}
void test(){
std::cout << "hellp" << std::endl;
}
int main(int argc, char const *argv[])
{
ThreadPool *poll = new ThreadPool();
std::function<void()> func = std::bind(print, 1, 3.14, "hello", std::string("world"));
poll->add(func);
func = test;
poll->add(func);
delete poll;
return 0;
}
================================================
FILE: code/day12/client.cpp
================================================
#include <iostream>
#include <unistd.h>
#include <string.h>
#include "src/util.h"
#include "src/Buffer.h"
#include "src/Socket.h"
using namespace std;
int main() {
Socket *sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->connect(addr);
int sockfd = sock->getFd();
Buffer *sendBuffer = new Buffer();
Buffer *readBuffer = new Buffer();
while(true){
sendBuffer->getline();
ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size());
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
int already_read = 0;
char buf[1024]; //这个buf大小无所谓
while(true){
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
readBuffer->append(buf, read_bytes);
already_read += read_bytes;
} else if(read_bytes == 0){ //EOF
printf("server disconnected!\n");
exit(EXIT_SUCCESS);
}
if(already_read >= sendBuffer->size()){
printf("message from server: %s\n", readBuffer->c_str());
break;
}
}
readBuffer->clear();
}
delete addr;
delete sock;
return 0;
}
================================================
FILE: code/day12/server.cpp
================================================
#include "src/EventLoop.h"
#include "src/Server.h"
int main() {
EventLoop *loop = new EventLoop();
Server *server = new Server(loop);
loop->loop();
return 0;
}
================================================
FILE: code/day12/src/Acceptor.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Acceptor.h"
#include "Socket.h"
#include "Channel.h"
Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){
sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
sock->bind(addr);
// sock->setnonblocking(); acceptor使用阻塞式IO比较好
sock->listen();
acceptChannel = new Channel(loop, sock->getFd());
std::function<void()> cb = std::bind(&Acceptor::acceptConnection, this);
acceptChannel->setReadCallback(cb);
acceptChannel->enableRead();
delete addr;
}
Acceptor::~Acceptor(){
delete sock;
delete acceptChannel;
}
void Acceptor::acceptConnection(){
InetAddress *clnt_addr = new InetAddress();
Socket *clnt_sock = new Socket(sock->accept(clnt_addr));
printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), clnt_addr->getIp(), clnt_addr->getPort());
clnt_sock->setnonblocking(); //新接受到的连接设置为非阻塞式
newConnectionCallback(clnt_sock);
delete clnt_addr;
}
void Acceptor::setNewConnectionCallback(std::function<void(Socket*)> _cb){
newConnectionCallback = _cb;
}
================================================
FILE: code/day12/src/Acceptor.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class EventLoop;
class Socket;
class Channel;
class Acceptor
{
private:
EventLoop *loop;
Socket *sock;
Channel *acceptChannel;
std::function<void(Socket*)> newConnectionCallback;
public:
Acceptor(EventLoop *_loop);
~Acceptor();
void acceptConnection();
void setNewConnectionCallback(std::function<void(Socket*)>);
};
================================================
FILE: code/day12/src/Buffer.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Buffer.h"
#include <string.h>
#include <iostream>
Buffer::Buffer() {}
Buffer::~Buffer() {}
void Buffer::append(const char* _str, int _size){
for(int i = 0; i < _size; ++i){
if(_str[i] == '\0') break;
buf.push_back(_str[i]);
}
}
ssize_t Buffer::size(){
return buf.size();
}
const char* Buffer::c_str(){
return buf.c_str();
}
void Buffer::clear(){
buf.clear();
}
void Buffer::getline(){
buf.clear();
std::getline(std::cin, buf);
}
void Buffer::setBuf(const char* _buf){
buf.clear();
buf.append(_buf);
}
================================================
FILE: code/day12/src/Buffer.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <string>
class Buffer
{
private:
std::string buf;
public:
Buffer();
~Buffer();
void append(const char* _str, int _size);
ssize_t size();
const char* c_str();
void clear();
void getline();
void setBuf(const char*);
};
================================================
FILE: code/day12/src/Channel.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Channel.h"
#include "EventLoop.h"
#include "Socket.h"
#include <unistd.h>
#include <sys/epoll.h>
Channel::Channel(EventLoop *_loop, int _fd)
: loop(_loop), fd(_fd), events(0), ready(0), inEpoll(false){}
Channel::~Channel(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Channel::handleEvent(){
if(ready & (EPOLLIN | EPOLLPRI)){
readCallback();
}
if(ready & (EPOLLOUT)){
writeCallback();
}
}
void Channel::enableRead(){
events |= EPOLLIN | EPOLLPRI;
loop->updateChannel(this);
}
void Channel::useET(){
events |= EPOLLET;
loop->updateChannel(this);
}
int Channel::getFd(){
return fd;
}
uint32_t Channel::getEvents(){
return events;
}
uint32_t Channel::getReady(){
return ready;
}
bool Channel::getInEpoll(){
return inEpoll;
}
void Channel::setInEpoll(bool _in){
inEpoll = _in;
}
void Channel::setReady(uint32_t _ev){
ready = _ev;
}
void Channel::setReadCallback(std::function<void()> _cb){
readCallback = _cb;
}
================================================
FILE: code/day12/src/Channel.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class Socket;
class EventLoop;
class Channel
{
private:
EventLoop *loop;
int fd;
uint32_t events;
uint32_t ready;
bool inEpoll;
std::function<void()> readCallback;
std::function<void()> writeCallback;
public:
Channel(EventLoop *_loop, int _fd);
~Channel();
void handleEvent();
void enableRead();
int getFd();
uint32_t getEvents();
uint32_t getReady();
bool getInEpoll();
void setInEpoll(bool _in = true);
void useET();
void setReady(uint32_t);
void setReadCallback(std::function<void()>);
};
================================================
FILE: code/day12/src/Connection.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Connection.h"
#include "Socket.h"
#include "Channel.h"
#include "util.h"
#include "Buffer.h"
#include <unistd.h>
#include <string.h>
#include <iostream>
Connection::Connection(EventLoop *_loop, Socket *_sock) : loop(_loop), sock(_sock), channel(nullptr), readBuffer(nullptr){
channel = new Channel(loop, sock->getFd());
channel->enableRead();
channel->useET();
std::function<void()> cb = std::bind(&Connection::echo, this, sock->getFd());
channel->setReadCallback(cb);
readBuffer = new Buffer();
}
Connection::~Connection(){
delete channel;
delete sock;
delete readBuffer;
}
void Connection::setDeleteConnectionCallback(std::function<void(int)> _cb){
deleteConnectionCallback = _cb;
}
void Connection::echo(int sockfd){
char buf[1024]; //这个buf大小无所谓
while(true){ //由于使用非阻塞IO,读取客户端buffer,一次读取buf大小数据,直到全部读取完毕
bzero(&buf, sizeof(buf));
ssize_t bytes_read = read(sockfd, buf, sizeof(buf));
if(bytes_read > 0){
readBuffer->append(buf, bytes_read);
} else if(bytes_read == -1 && errno == EINTR){ //客户端正常中断、继续读取
printf("continue reading\n");
continue;
} else if(bytes_read == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){//非阻塞IO,这个条件表示数据全部读取完毕
printf("message from client fd %d: %s\n", sockfd, readBuffer->c_str());
// errif(write(sockfd, readBuffer->c_str(), readBuffer->size()) == -1, "socket write error");
send(sockfd);
readBuffer->clear();
break;
} else if(bytes_read == 0){ //EOF,客户端断开连接
printf("EOF, client fd %d disconnected\n", sockfd);
deleteConnectionCallback(sockfd);
break;
} else {
printf("Connection reset by peer\n");
deleteConnectionCallback(sockfd);
break;
}
}
}
void Connection::send(int sockfd){
char buf[readBuffer->size()];
strcpy(buf, readBuffer->c_str());
int data_size = readBuffer->size();
int data_left = data_size;
while (data_left > 0)
{
ssize_t bytes_write = write(sockfd, buf + data_size - data_left, data_left);
if (bytes_write == -1 && errno == EAGAIN) {
break;
}
data_left -= bytes_write;
}
}
================================================
FILE: code/day12/src/Connection.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class EventLoop;
class Socket;
class Channel;
class Buffer;
class Connection
{
private:
EventLoop *loop;
Socket *sock;
Channel *channel;
std::function<void(int)> deleteConnectionCallback;
Buffer *readBuffer;
public:
Connection(EventLoop *_loop, Socket *_sock);
~Connection();
void echo(int sockfd);
void setDeleteConnectionCallback(std::function<void(int)>);
void send(int sockfd);
};
================================================
FILE: code/day12/src/Epoll.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Epoll.h"
#include "util.h"
#include "Channel.h"
#include <unistd.h>
#include <string.h>
#define MAX_EVENTS 1000
Epoll::Epoll() : epfd(-1), events(nullptr){
epfd = epoll_create1(0);
errif(epfd == -1, "epoll create error");
events = new epoll_event[MAX_EVENTS];
bzero(events, sizeof(*events) * MAX_EVENTS);
}
Epoll::~Epoll(){
if(epfd != -1){
close(epfd);
epfd = -1;
}
delete [] events;
}
std::vector<Channel*> Epoll::poll(int timeout){
std::vector<Channel*> activeChannels;
int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
errif(nfds == -1, "epoll wait error");
for(int i = 0; i < nfds; ++i){
Channel *ch = (Channel*)events[i].data.ptr;
ch->setReady(events[i].events);
activeChannels.push_back(ch);
}
return activeChannels;
}
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd();
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents();
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");
channel->setInEpoll();
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");
}
}
void Epoll::deleteChannel(Channel *channel){
int fd = channel->getFd();
errif(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) == -1, "epoll delete error");
channel->setInEpoll(false);
}
================================================
FILE: code/day12/src/Epoll.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <sys/epoll.h>
#include <vector>
class Channel;
class Epoll
{
private:
int epfd;
struct epoll_event *events;
public:
Epoll();
~Epoll();
void updateChannel(Channel*);
void deleteChannel(Channel*);
std::vector<Channel*> poll(int timeout = -1);
};
================================================
FILE: code/day12/src/EventLoop.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "EventLoop.h"
#include "Epoll.h"
#include "Channel.h"
#include <vector>
EventLoop::EventLoop() : ep(nullptr), quit(false){
ep = new Epoll();
}
EventLoop::~EventLoop(){
delete ep;
}
void EventLoop::loop(){
while(!quit){
std::vector<Channel*> chs;
chs = ep->poll();
for(auto it = chs.begin(); it != chs.end(); ++it){
(*it)->handleEvent();
}
}
}
void EventLoop::updateChannel(Channel *ch){
ep->updateChannel(ch);
}
================================================
FILE: code/day12/src/EventLoop.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
class Epoll;
class Channel;
class EventLoop
{
private:
Epoll *ep;
bool quit;
public:
EventLoop();
~EventLoop();
void loop();
void updateChannel(Channel*);
void addThread(std::function<void()>);
};
================================================
FILE: code/day12/src/Server.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "Server.h"
#include "Socket.h"
#include "Acceptor.h"
#include "Connection.h"
#include "ThreadPool.h"
#include "EventLoop.h"
#include <unistd.h>
#include <functional>
Server::Server(EventLoop *_loop) : mainReactor(_loop), acceptor(nullptr){
acceptor = new Acceptor(mainReactor);
std::function<void(Socket*)> cb = std::bind(&Server::newConnection, this, std::placeholders::_1);
acceptor->setNewConnectionCallback(cb);
int size = std::thread::hardware_concurrency();
thpool = new ThreadPool(size);
for(int i = 0; i < size; ++i){
subReactors.push_back(new EventLoop());
}
for(int i = 0; i < size; ++i){
std::function<void()> sub_loop = std::bind(&EventLoop::loop, subReactors[i]);
thpool->add(sub_loop);
}
}
Server::~Server(){
delete acceptor;
delete thpool;
}
void Server::newConnection(Socket *sock){
if(sock->getFd() != -1){
int random = sock->getFd() % subReactors.size();
Connection *conn = new Connection(subReactors[random], sock);
std::function<void(int)> cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1);
conn->setDeleteConnectionCallback(cb);
connections[sock->getFd()] = conn;
}
}
void Server::deleteConnection(int sockfd){
if(sockfd != -1){
auto it = connections.find(sockfd);
if(it != connections.end()){
Connection *conn = connections[sockfd];
connections.erase(sockfd);
// close(sockfd); //正常
delete conn; //会Segmant fault
}
}
}
================================================
FILE: code/day12/src/Server.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <map>
#include <vector>
class EventLoop;
class Socket;
class Acceptor;
class Connection;
class ThreadPool;
class Server
{
private:
EventLoop *mainReactor;
Acceptor *acceptor;
std::map<int, Connection*> connections;
std::vector<EventLoop*> subReactors;
ThreadPool *thpool;
public:
Server(EventLoop*);
~Server();
void handleReadEvent(int);
void newConnection(Socket *sock);
void deleteConnection(int sockfd);
};
================================================
FILE: code/day12/src/Socket.cpp
================================================
/******************************
* author: yuesong-feng
* 客户端、服务器共用
* accept,connect都支持非阻塞式IO,但只是简单处理,如果情况太复杂可能会有意料之外的bug
*
******************************/
#include "Socket.h"
#include "util.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
Socket::Socket() : fd(-1){
fd = socket(AF_INET, SOCK_STREAM, 0);
errif(fd == -1, "socket create error");
}
Socket::Socket(int _fd) : fd(_fd){
errif(fd == -1, "socket create error");
}
Socket::~Socket(){
if(fd != -1){
close(fd);
fd = -1;
}
}
void Socket::bind(InetAddress *_addr){
struct sockaddr_in addr = _addr->getAddr();
errif(::bind(fd, (sockaddr*)&addr, sizeof(addr)) == -1, "socket bind error");
}
void Socket::listen(){
errif(::listen(fd, SOMAXCONN) == -1, "socket listen error");
}
void Socket::setnonblocking(){
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
int Socket::accept(InetAddress *_addr){
// for server socket
int clnt_sockfd = -1;
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
socklen_t addr_len = sizeof(addr);
if(fcntl(fd, F_GETFL) & O_NONBLOCK){
while(true){
clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len);
if(clnt_sockfd == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))){
// printf("no connection yet\n");
continue;
} else if(clnt_sockfd == -1){
errif(true, "socket accept error");
} else{
break;
}
}
}
else{
clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len);
errif(clnt_sockfd == -1, "socket accept error");
}
_addr->setInetAddr(addr);
return clnt_sockfd;
}
void Socket::connect(InetAddress *_addr){
// for client socket
struct sockaddr_in addr = _addr->getAddr();
if(fcntl(fd, F_GETFL) & O_NONBLOCK){
while(true){
int ret = ::connect(fd, (sockaddr*)&addr, sizeof(addr));
if(ret == 0){
break;
} else if(ret == -1 && (errno == EINPROGRESS)){
continue;
/* 连接非阻塞式sockfd建议的做法:
The socket is nonblocking and the connection cannot be
completed immediately. (UNIX domain sockets failed with
EAGAIN instead.) It is possible to select(2) or poll(2)
for completion by selecting the socket for writing. After
select(2) indicates writability, use getsockopt(2) to read
the SO_ERROR option at level SOL_SOCKET to determine
whether connect() completed successfully (SO_ERROR is
zero) or unsuccessfully (SO_ERROR is one of the usual
error codes listed here, explaining the reason for the
failure).
这里为了简单、不断连接直到连接完成,相当于阻塞式
*/
} else if(ret == -1){
errif(true, "socket connect error");
}
}
} else{
errif(::connect(fd, (sockaddr*)&addr, sizeof(addr)) == -1, "socket connect error");
}
}
int Socket::getFd(){
return fd;
}
InetAddress::InetAddress() {
bzero(&addr, sizeof(addr));
}
InetAddress::InetAddress(const char* _ip, uint16_t _port) {
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(_ip);
addr.sin_port = htons(_port);
}
InetAddress::~InetAddress(){
}
void InetAddress::setInetAddr(sockaddr_in _addr){
addr = _addr;
}
sockaddr_in InetAddress::getAddr(){
return addr;
}
char* InetAddress::getIp(){
return inet_ntoa(addr.sin_addr);
}
uint16_t InetAddress::getPort(){
return ntohs(addr.sin_port);
}
================================================
FILE: code/day12/src/Socket.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <arpa/inet.h>
class InetAddress
{
private:
struct sockaddr_in addr;
public:
InetAddress();
InetAddress(const char* _ip, uint16_t _port);
~InetAddress();
void setInetAddr(sockaddr_in _addr);
sockaddr_in getAddr();
char* getIp();
uint16_t getPort();
};
class Socket
{
private:
int fd;
public:
Socket();
Socket(int _fd);
~Socket();
void bind(InetAddress*);
void listen();
int accept(InetAddress*);
void connect(InetAddress*);
void setnonblocking();
int getFd();
};
================================================
FILE: code/day12/src/ThreadPool.cpp
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#include "ThreadPool.h"
ThreadPool::ThreadPool(int size) : stop(false){
for(int i = 0; i < size; ++i){
threads.emplace_back(std::thread([this](){
while(true){
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(tasks_mtx);
cv.wait(lock, [this](){
return stop || !tasks.empty();
});
if(stop && tasks.empty()) return;
task = tasks.front();
tasks.pop();
}
task();
}
}));
}
}
ThreadPool::~ThreadPool(){
{
std::unique_lock<std::mutex> lock(tasks_mtx);
stop = true;
}
cv.notify_all();
for(std::thread &th : threads){
if(th.joinable())
th.join();
}
}
================================================
FILE: code/day12/src/ThreadPool.h
================================================
/******************************
* author: yuesong-feng
*
*
*
******************************/
#pragma once
#include <functional>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
class ThreadPool
{
private:
std::vector<std::thread> threads;
std::queue<std::function<void()>> tasks;
std::mutex tasks_mtx;
std::condition_variable cv;
bool stop;
public:
ThreadPool(int size = std::thread::hardware_concurrency());
~ThreadPool();
// void add(std::function<void()>);
template<class F, class... Args>
auto add(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;
};
//不能放在cpp文件,C++编译器不支持模版的分离编译
template<class F, class... Args>
auto ThreadPool::add(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>
{
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(tasks_mtx);
// don't allow enqueueing after stopping the pool
if(stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task](){ (*task)(); });
}
cv.notify_one();
return res;
}
================================================
FILE: code/day12/src/util.cpp
================================================
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
void errif(bool condition, const char *errmsg){
if(condition){
perror(errmsg);
exit(EXIT_FAILURE);
}
}
================================================
FILE: code/day12/src/util.h
================================================
#ifndef UTIL_H
#define UTIL_H
void errif(bool, const char*);
#endif
================================================
FILE: code/day12/test.cpp
================================================
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <functional>
#include "src/util.h"
#include "src/Buffer.h"
#include "src/Socket.h"
#include "src/ThreadPool.h"
using namespace std;
void oneClient(int msgs, int wait){
Socket *sock = new Socket();
InetAddress *addr = new InetAddress("127.0.0.1", 1234);
// sock->setnonblocking(); 客户端使用阻塞式连接比较好,方便简单不容易出错
sock->connect(addr);
int sockfd = sock->getFd();
Buffer *sendBuffer = new Buffer();
Buffer *readBuffer = new Buffer();
sleep(wait);
int count = 0;
while(count < msgs){
sendBuffer->setBuf("I'm client!");
ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size());
if(write_bytes == -1){
printf("socket already disconnected, can't write any more!\n");
break;
}
int already_read = 0;
char buf[1024]; //这个buf大小无所谓
while(true){
bzero(&buf, sizeof(buf));
ssize_t read_bytes = read(sockfd, buf, sizeof(buf));
if(read_bytes > 0){
readBuffer->append(buf, read_bytes);
already_read += read_bytes;
} else if(read_bytes == 0){ //EOF
printf("server disconnected!\n");
exit(EXIT_SUCCESS);
}
if(already_read >= sendBuffer->size()){
printf("count: %d, message from server: %s\n", count++, readBuffer->c_str());
break;
}
}
readBuffer->clear();
}
delete addr;
delete sock;
}
int main(int argc, char *argv[]) {
int threads = 100;
int msgs = 100;
int wait = 0;
int o;
const char *optstring = "t:m:w:";
while ((o = getopt(argc, argv, optstring)) != -1) {
switch (o) {
case 't':
threads = stoi(optarg);
break;
case 'm':
msgs = stoi(optarg);
break;
case 'w':
wait = stoi(optarg);
break;
case '?':
printf("error optopt: %c\n", optopt);
printf("error opterr: %d\n", opterr);
break;
}
}
ThreadPool *poll = new ThreadPool(threads);
std::function<void()> func = std::bind(oneClient, msgs, wait);
for(int i = 0; i < threads; ++i){
poll->add(func);
}
delete poll;
return 0;
}
================================================
FILE: code/day13/.clang-format
================================================
BasedOnStyle: Google
DerivePointerAlignment: false
PointerAlignment: Right
ColumnLimit: 120
# Default for clang-8, changed in later clangs. Set explicitly for forwards
# compatibility with modern clangs
IncludeBlocks: Preserve
================================================
FILE: code/day13/.clang-tidy
================================================
---
Checks: '
bugprone-*,
-bugprone-exception-escape,
clang-analyzer-*,
concurrency-*,
cppcoreguidelines-*,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-cstyle-cast,
google-*,
-google-readability-casting,
hicpp-*,
-hicpp-vararg,
-hicpp-use-auto,
-hicpp-no-array-decay,
-hicpp-avoid-c-arrays,
-hicpp-signed-bitwise,
modernize-*,
-modernize-use-trailing-return-type,
-modernize-avoid-bind,
-modernize-avoid-c-arrays,
-modernize-use-auto,
performance-*,
portability-*,
readability-*,
-readability-magic-numbers,
-readability-make-member-function-const,
-readability-implicit-bool-conversion,
'
CheckOptions:
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.FunctionCase, value: CamelCase }
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.MemberCase, value: lower_case }
- { key: readability-identifier-naming.MemberSuffix, value: _ }
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.UnionCase, value: CamelCase }
- { key: readability-identifier-naming.VariableCase, value: lower_case }
WarningsAsErrors: '*'
HeaderFilterRegex: '/(src|test)/include'
AnalyzeTemporaryDtors: true
================================================
FILE: code/day13/.gitignore
================================================
build/
*__pycache__/
.vscode/settings.json
================================================
FILE: code/day13/.vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/test/server",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
================================================
FILE: code/day13/CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.10)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(BUILD_SHARED_LIBS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
project(Pine
VERSION 0.1
DESCRIPTION "pine"
LANGUAGES C CXX
)
# People keep running CMake in the wrong folder, completely nuking their project or creating weird bugs.
# This checks if you're running CMake from a folder that already has CMakeLists.txt.
# Importantly, this catches the common case of running it from the root directory.
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" PATH_TO_CMAKELISTS_TXT)
if (EXISTS "${PATH_TO_CMAKELISTS_TXT}")
message(FATAL_ERROR "Run CMake from a build subdirectory! \"mkdir build ; cd build ; cmake .. \" \
Some junk files were created in this folder (CMakeCache.txt, CMakeFiles); you should delete those.")
endif ()
# Expected directory structure.
set(PINE_BUILD_SUPPORT_DIR "${CMAKE_SOURCE_DIR}/build_support")
set(PINE_CLANG_SEARCH_PATH "/usr/local/bin" "/usr/bin" "/usr/local/opt/llvm/bin" "/usr/local/opt/llvm@8/bin" "/usr/local/Cellar/llvm/8.0.1/bin")
######################################################################################################################
# DEPENDENCIES
######################################################################################################################
# CTest
# enable_testing()
# clang-format
if (NOT DEFINED CLANG_FORMAT_BIN)
# attempt to find the binary if user did not specify
find_program(CLANG_FORMAT_BIN
NAMES clang-format clang-format-8
HINTS ${PINE_CLANG_SEARCH_PATH})
endif ()
if ("${CLANG_FORMAT_BIN}" STREQUAL "CLANG_FORMAT_BIN-NOTFOUND")
message(WARNING "Pine/main couldn't find clang-format.")
else ()
message(STATUS "Pine/main found clang-format at ${CLANG_FORMAT_BIN}")
endif ()
# clang-tidy
if (NOT DEFINED CLANG_TIDY_BIN)
# attempt to find the binary if user did not specify
find_program(CLANG_TIDY_BIN
NAMES clang-tidy clang-fidy-8
HINTS ${PINE_CLANG_SEARCH_PATH})
endif ()
if ("${CLANG_TIDY_BIN}" STREQUAL "CLANG_TIDY_BIN-NOTFOUND")
message(WARNING "Pine/main couldn't find clang-tidy.")
else ()
# Output compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
message(STATUS "Pine/main found clang-fidy at ${CLANG_TIDY_BIN}")
endif ()
# cpplint
find_program(CPPLINT_BIN
NAMES cpplint cpplint.py
HINTS ${PINE_BUILD_SUPPORT_DIR})
if ("${CPPLINT_BIN}" STREQUAL "CPPLINT_BIN-NOTFOUND")
message(WARNING "Pine/main couldn't find cpplint.")
else ()
message(STATUS "Pine/main found cpplint at ${CPPLINT_BIN}")
endif ()
######################################################################################################################
# COMPILER SETUP
######################################################################################################################
# Compiler flags.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra -std=c++17 -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-attributes") #TODO: remove
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ggdb -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIC")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fPIC")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fPIC")
set(GCC_COVERAGE_LINK_FLAGS "-fPIC")
message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
message(STATUS "CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}")
message(STATUS "CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
message(STATUS "CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}")
# Output directory.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Includes.
set(PINE_SRC_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/src/include)
set(PINE_TEST_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/test/include)
include_directories(${PINE_SRC_INCLUDE_DIR} ${PINE_TEST_INCLUDE_DIR})
add_subdirectory(src)
add_subdirectory(test)
######################################################################################################################
# MAKE TARGETS
######################################################################################################################
##########################################
# "make format"
# "make check-format"
##########################################
string(CONCAT PINE_FORMAT_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/src,"
"${CMAKE_CURRENT_SOURCE_DIR}/test,"
)
# runs clang format and updates files in place.
add_custom_target(format ${PINE_BUILD_SUPPORT_DIR}/run_clang_format.py
${CLANG_FORMAT_BIN}
${PINE_BUILD_SUPPORT_DIR}/clang_format_exclusions.txt
--source_dirs
${PINE_FORMAT_DIRS}
--fix
--quiet
)
# runs clang format and exits with a non-zero exit code if any files need to be reformatted
add_custom_target(check-format ${PINE_BUILD_SUPPORT_DIR}/run_clang_format.py
${CLANG_FORMAT_BIN}
${PINE_BUILD_SUPPORT_DIR}/clang_format_exclusions.txt
--source_dirs
${PINE_FORMAT_DIRS}
--quiet
)
##########################################
# "make cpplint"
##########################################
file(GLOB_RECURSE PINE_LINT_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/test/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp"
)
# Balancing act: cpplint.py takes a non-trivial time to launch,
# so process 12 files per invocation, while still ensuring parallelism
add_custom_target(cpplint echo '${PINE_LINT_FILES}' | xargs -n12 -P8
${CPPLINT_BIN}
--verbose=2 --quiet
--linelength=120
--filter=-legal/copyright,-build/include_subdir,-readability/casting
)
###########################################################
# "make clang-tidy" target
###########################################################
# runs clang-tidy and exits with a non-zero exit code if any errors are found.
# note that clang-tidy automatically looks for a .clang-tidy file in parent directories
add_custom_target(clang-tidy
${PINE_BUILD_SUPPORT_DIR}/run_clang_tidy.py # run LLVM's clang-tidy script
-clang-tidy-binary ${CLANG_TIDY_BIN} # using our clang-tidy binary
-p ${CMAKE_BINARY_DIR} # using cmake's generated compile commands
)
# add_dependencies(check-clang-tidy pine_shared) # needs gtest headers, compile_commands.json
================================================
FILE: code/day13/build_support/clang_format_exclusions.txt
================================================
================================================
FILE: code/day13/build_support/cpplint.py
================================================
#!/usr/bin/env python
#
# Copyright (c) 2009 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Does google-lint on c++ files.
The goal of this script is to identify places in the code that *may*
be in non-compliance with google style. It does not attempt to fix
up these problems -- the point is to educate. It does also not
attempt to find all problems, or to ensure that everything it does
find is legitimately a problem.
In particular, we can get very confused by /* and // inside strings!
We do a small hack, which is to ignore //'s with "'s after them on the
same line, but it is far from perfect (in either direction).
"""
import codecs
import copy
import getopt
import glob
import itertools
import math # for log
import os
import re
import sre_compile
import string
import sys
import sysconfig
import unicodedata
import xml.etree.ElementTree
# if empty, use defaults
_valid_extensions = set([])
__VERSION__ = '1.4.4'
try:
xrange # Python 2
except NameError:
# -- pylint: disable=redefined-builtin
xrange = range # Python 3
_USAGE = """
Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit]
[--filter=-x,+y,...]
[--counting=total|toplevel|detailed] [--root=subdir]
[--repository=path]
[--linelength=digits] [--headers=x,y,...]
[--recursive]
[--exclude=path]
[--extensions=hpp,cpp,...]
[--quiet]
[--version]
<file> [file] ...
Style checker for C/C++ source files.
This is a fork of the Google style checker with minor extensions.
The style guidelines this tries to follow are those in
https://google.github.io/styleguide/cppguide.html
Every problem is given a confidence score from 1-5, with 5 meaning we are
certain of the problem, and 1 meaning it could be a legitimate construct.
This will miss some errors, and is not a substitute for a code review.
To suppress false-positive errors of a certain category, add a
'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
suppresses errors of all categories on that line.
The files passed in will be linted; at least one file must be provided.
Default linted extensions are %s.
Other file types will be ignored.
Change the extensions with the --extensions flag.
Flags:
output=emacs|eclipse|vs7|junit
By default, the output is formatted to ease emacs parsing. Visual Studio
compatible output (vs7) may also be used. Further support exists for
eclipse (eclipse), and JUnit (junit). XML parsers such as those used
in Jenkins and Bamboo may also be used. Other formats are unsupported.
verbose=#
Specify a number 0-5 to restrict errors to certain verbosity levels.
Errors with lower verbosity levels have lower confidence and are more
likely to be false positives.
quiet
Don't print anything if no errors are found.
filter=-x,+y,...
Specify a comma-separated list of category-filters to apply: only
error messages whose category names pass the filters will be printed.
(Category names are printed with the message and look like
"[whitespace/indent]".) Filters are evaluated left to right.
"-FOO" and "FOO" means "do not print categories that start with FOO".
"+FOO" means "do print categories that start with FOO".
Examples: --filter=-whitespace,+whitespace/braces
--filter=whitespace,runtime/printf,+runtime/printf_format
--filter=-,+build/include_what_you_use
To see a list of all the categories used in cpplint, pass no arg:
--filter=
counting=total|toplevel|detailed
The total number of errors found is always printed. If
'toplevel' is provided, then the count of errors in each of
the top-level categories like 'build' and 'whitespace' will
also be printed. If 'detailed' is provided, then a count
is provided for each category like 'build/class'.
repository=path
The top level directory of the repository, used to derive the header
guard CPP variable. By default, this is determined by searching for a
path that contains .git, .hg, or .svn. When this flag is specified, the
given path is used instead. This option allows the header guard CPP
variable to remain consistent even if members of a team have different
repository root directories (such as when checking out a subdirectory
with SVN). In addition, users of non-mainstream version control systems
can use this flag to ensure readable header guard CPP variables.
Examples:
Assuming that Alice checks out ProjectName and Bob checks out
ProjectName/trunk and trunk contains src/chrome/ui/browser.h, then
with no --repository flag, the header guard CPP variable will be:
Alice => TRUNK_SRC_CHROME_BROWSER_UI_BROWSER_H_
Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_
If Alice uses the --repository=trunk flag and Bob omits the flag or
uses --repository=. then the header guard CPP variable will be:
Alice => SRC_CHROME_BROWSER_UI_BROWSER_H_
Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_
root=subdir
The root directory used for deriving header guard CPP variable.
This directory is relative to the top level directory of the repository
which by default is determined by searching for a directory that contains
.git, .hg, or .svn but can also be controlled with the --repository flag.
If the specified directory does not exist, this flag is ignored.
Examples:
Assuming that src is the top level directory of the repository (and
cwd=top/src), the header guard CPP variables for
src/chrome/browser/ui/browser.h are:
No flag => CHROME_BROWSER_UI_BROWSER_H_
--root=chrome => BROWSER_UI_BROWSER_H_
--root=chrome/browser => UI_BROWSER_H_
--root=.. => SRC_CHROME_BROWSER_UI_BROWSER_H_
linelength=digits
This is the allowed line length for the project. The default value is
80 characters.
Examples:
--linelength=120
recursive
Search for files to lint recursively. Each directory given in the list
of files to be linted is replaced by all files that descend from that
directory. Files with extensions not in the valid extensions list are
excluded.
exclude=path
Exclude the given path from the list of files to be linted. Relative
paths are evaluated relative to the current directory and shell globbing
is performed. This flag can be provided multiple times to exclude
multiple files.
Examples:
--exclude=one.cc
--exclude=src/*.cc
--exclude=src/*.cc --exclude=test/*.cc
extensions=extension,extension,...
The allowed file extensions that cpplint will check
Examples:
--extensions=%s
headers=x,y,...
The header extensions that cpplint will treat as .h in checks. Values are
automatically added to --extensions list.
(by default, only files with extensions %s will be assumed to be headers)
Examples:
--headers=%s
--headers=hpp,hxx
--headers=hpp
cpplint.py supports per-directory configurations specified in CPPLINT.cfg
files. CPPLINT.cfg file can contain a number of key=value pairs.
Currently the following options are supported:
set noparent
filter=+filter1,-filter2,...
exclude_files=regex
linelength=80
root=subdir
headers=x,y,...
"set noparent" option prevents cpplint from traversing directory tree
upwards looking for more .cfg files in parent directories. This option
is usually placed in the top-level project directory.
The "filter" option is similar in function to --filter flag. It specifies
message filters in addition to the |_DEFAULT_FILTERS| and those specified
through --filter command-line flag.
"exclude_files" allows to specify a regular expression to be matched against
a file name. If the expression matches, the file is skipped and not run
through the linter.
"linelength" allows to specify the allowed line length for the project.
The "root" option is similar in function to the --root flag (see example
above). Paths are relative to the directory of the CPPLINT.cfg.
The "headers" option is similar in function to the --headers flag
(see example above).
CPPLINT.cfg has an effect on files in the same directory and all
sub-directories, unless overridden by a nested configuration file.
Example file:
filter=-build/include_order,+build/include_alpha
exclude_files=.*\\.cc
The above example disables build/include_order warning and enables
build/include_alpha as well as excludes all .cc from being
processed by linter, in the current directory (where the .cfg
file is located) and all sub-directories.
"""
# We categorize each error message we print. Here are the categories.
# We want an explicit list so we can list them all in cpplint --filter=.
# If you add a new error message with a new category, add it to the list
# here! cpplint_unittest.py should tell you if you forget to do this.
_ERROR_CATEGORIES = [
'build/class',
'build/c++11',
'build/c++14',
'build/c++tr1',
'build/deprecated',
'build/endif_comment',
'build/explicit_make_pair',
'build/forward_decl',
'build/header_guard',
'build/include',
'build/include_subdir',
'build/include_alpha',
'build/include_order',
'build/include_what_you_use',
'build/namespaces_literals',
'build/namespaces',
'build/printf_format',
'build/storage_class',
'legal/copyright',
'readability/alt_tokens',
'readability/braces',
'readability/casting',
'readability/check',
'readability/constructors',
'readability/fn_size',
'readability/inheritance',
'readability/multiline_comment',
'readability/multiline_string',
'readability/namespace',
'readability/nolint',
'readability/nul',
'readability/strings',
'readability/todo',
'readability/utf8',
'runtime/arrays',
'runtime/casting',
'runtime/explicit',
'runtime/int',
'runtime/init',
'runtime/invalid_increment',
'runtime/member_string_references',
'runtime/memset',
'runtime/indentation_namespace',
'runtime/operator',
'runtime/printf',
'runtime/printf_format',
'runtime/references',
'runtime/string',
'runtime/threadsafe_fn',
'runtime/vlog',
'whitespace/blank_line',
'whitespace/braces',
'whitespace/comma',
'whitespace/comments',
'whitespace/empty_conditional_body',
'whitespace/empty_if_body',
'whitespace/empty_loop_body',
'whitespace/end_of_line',
'whitespace/ending_newline',
'whitespace/forcolon',
'whitespace/indent',
'whitespace/line_length',
'whitespace/newline',
'whitespace/operators',
'whitespace/parens',
'whitespace/semicolon',
'whitespace/tab',
'whitespace/todo',
]
# These error categories are no longer enforced by cpplint, but for backwards-
# compatibility they may still appear in NOLINT comments.
_LEGACY_ERROR_CATEGORIES = [
'readability/streams',
'readability/function',
]
# The default state of the category filter. This is overridden by the --filter=
# flag. By default all errors are on, so only add here categories that should be
# off by default (i.e., categories that must be enabled by the --filter= flags).
# All entries here should start with a '-' or '+', as in the --filter= flag.
_DEFAULT_FILTERS = ['-build/include_alpha']
# The default list of categories suppressed for C (not C++) files.
_DEFAULT_C_SUPPRESSED_CATEGORIES = [
'readability/casting',
]
# The default list of categories suppressed for Linux Kernel files.
_DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
'whitespace/tab',
]
# We u
gitextract_3td5mg8d/ ├── README.md ├── code/ │ ├── day01/ │ │ ├── Makefile │ │ ├── client.cpp │ │ └── server.cpp │ ├── day02/ │ │ ├── Makefile │ │ ├── client.cpp │ │ ├── server.cpp │ │ ├── util.cpp │ │ └── util.h │ ├── day03/ │ │ ├── Makefile │ │ ├── client.cpp │ │ ├── server.cpp │ │ ├── util.cpp │ │ └── util.h │ ├── day04/ │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Makefile │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── client.cpp │ │ ├── server.cpp │ │ ├── util.cpp │ │ └── util.h │ ├── day05/ │ │ ├── Channel.cpp │ │ ├── Channel.h │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Makefile │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── client.cpp │ │ ├── server.cpp │ │ ├── util.cpp │ │ └── util.h │ ├── day06/ │ │ ├── Makefile │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── src/ │ │ ├── Channel.cpp │ │ ├── Channel.h │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── EventLoop.cpp │ │ ├── EventLoop.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Server.cpp │ │ ├── Server.h │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── util.cpp │ │ └── util.h │ ├── day07/ │ │ ├── Makefile │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── src/ │ │ ├── Acceptor.cpp │ │ ├── Acceptor.h │ │ ├── Channel.cpp │ │ ├── Channel.h │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── EventLoop.cpp │ │ ├── EventLoop.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Server.cpp │ │ ├── Server.h │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── util.cpp │ │ └── util.h │ ├── day08/ │ │ ├── Makefile │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── src/ │ │ ├── Acceptor.cpp │ │ ├── Acceptor.h │ │ ├── Channel.cpp │ │ ├── Channel.h │ │ ├── Connection.cpp │ │ ├── Connection.h │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── EventLoop.cpp │ │ ├── EventLoop.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Server.cpp │ │ ├── Server.h │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── util.cpp │ │ └── util.h │ ├── day09/ │ │ ├── Makefile │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── src/ │ │ ├── Acceptor.cpp │ │ ├── Acceptor.h │ │ ├── Buffer.cpp │ │ ├── Buffer.h │ │ ├── Channel.cpp │ │ ├── Channel.h │ │ ├── Connection.cpp │ │ ├── Connection.h │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── EventLoop.cpp │ │ ├── EventLoop.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Server.cpp │ │ ├── Server.h │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── util.cpp │ │ └── util.h │ ├── day10/ │ │ ├── Makefile │ │ ├── ThreadPoolTest.cpp │ │ ├── client.cpp │ │ ├── server.cpp │ │ └── src/ │ │ ├── Acceptor.cpp │ │ ├── Acceptor.h │ │ ├── Buffer.cpp │ │ ├── Buffer.h │ │ ├── Channel.cpp │ │ ├── Channel.h │ │ ├── Connection.cpp │ │ ├── Connection.h │ │ ├── Epoll.cpp │ │ ├── Epoll.h │ │ ├── EventLoop.cpp │ │ ├── EventLoop.h │ │ ├── InetAddress.cpp │ │ ├── InetAddress.h │ │ ├── Server.cpp │ │ ├── Server.h │ │ ├── Socket.cpp │ │ ├── Socket.h │ │ ├── ThreadPool.cpp │ │ ├── ThreadPool.h │ │ ├── util.cpp │ │ └── util.h │ ├── day11/ │ │ ├── .vscode/ │ │ │ └── launch.json │ │ ├── Makefile │ │ ├── ThreadPoolTest.cpp │ │ ├── client.cpp │ │ ├── server.cpp │ │ ├── src/ │ │ │ ├── Acceptor.cpp │ │ │ ├── Acceptor.h │ │ │ ├── Buffer.cpp │ │ │ ├── Buffer.h │ │ │ ├── Channel.cpp │ │ │ ├── Channel.h │ │ │ ├── Connection.cpp │ │ │ ├── Connection.h │ │ │ ├── Epoll.cpp │ │ │ ├── Epoll.h │ │ │ ├── EventLoop.cpp │ │ │ ├── EventLoop.h │ │ │ ├── InetAddress.cpp │ │ │ ├── InetAddress.h │ │ │ ├── Server.cpp │ │ │ ├── Server.h │ │ │ ├── Socket.cpp │ │ │ ├── Socket.h │ │ │ ├── ThreadPool.cpp │ │ │ ├── ThreadPool.h │ │ │ ├── util.cpp │ │ │ └── util.h │ │ └── test.cpp │ ├── day12/ │ │ ├── .vscode/ │ │ │ └── launch.json │ │ ├── Makefile │ │ ├── ThreadPoolTest.cpp │ │ ├── client.cpp │ │ ├── server.cpp │ │ ├── src/ │ │ │ ├── Acceptor.cpp │ │ │ ├── Acceptor.h │ │ │ ├── Buffer.cpp │ │ │ ├── Buffer.h │ │ │ ├── Channel.cpp │ │ │ ├── Channel.h │ │ │ ├── Connection.cpp │ │ │ ├── Connection.h │ │ │ ├── Epoll.cpp │ │ │ ├── Epoll.h │ │ │ ├── EventLoop.cpp │ │ │ ├── EventLoop.h │ │ │ ├── Server.cpp │ │ │ ├── Server.h │ │ │ ├── Socket.cpp │ │ │ ├── Socket.h │ │ │ ├── ThreadPool.cpp │ │ │ ├── ThreadPool.h │ │ │ ├── util.cpp │ │ │ └── util.h │ │ └── test.cpp │ ├── day13/ │ │ ├── .clang-format │ │ ├── .clang-tidy │ │ ├── .gitignore │ │ ├── .vscode/ │ │ │ └── launch.json │ │ ├── CMakeLists.txt │ │ ├── build_support/ │ │ │ ├── clang_format_exclusions.txt │ │ │ ├── cpplint.py │ │ │ ├── run_clang_format.py │ │ │ ├── run_clang_tidy.py │ │ │ └── run_clang_tidy_extra.py │ │ ├── src/ │ │ │ ├── Acceptor.cpp │ │ │ ├── Buffer.cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── Channel.cpp │ │ │ ├── Connection.cpp │ │ │ ├── Epoll.cpp │ │ │ ├── EventLoop.cpp │ │ │ ├── Server.cpp │ │ │ ├── Socket.cpp │ │ │ ├── ThreadPool.cpp │ │ │ ├── include/ │ │ │ │ ├── Acceptor.h │ │ │ │ ├── Buffer.h │ │ │ │ ├── Channel.h │ │ │ │ ├── Connection.h │ │ │ │ ├── Epoll.h │ │ │ │ ├── EventLoop.h │ │ │ │ ├── Macros.h │ │ │ │ ├── Server.h │ │ │ │ ├── Socket.h │ │ │ │ ├── ThreadPool.h │ │ │ │ └── util.h │ │ │ └── util.cpp │ │ └── test/ │ │ ├── CMakeLists.txt │ │ ├── multiple_client.cpp │ │ ├── server.cpp │ │ ├── single_client.cpp │ │ └── thread_test.cpp │ ├── day14/ │ │ ├── .clang-format │ │ ├── .clang-tidy │ │ ├── .gitignore │ │ ├── .vscode/ │ │ │ └── launch.json │ │ ├── CMakeLists.txt │ │ ├── build_support/ │ │ │ ├── clang_format_exclusions.txt │ │ │ ├── cpplint.py │ │ │ ├── run_clang_format.py │ │ │ ├── run_clang_tidy.py │ │ │ └── run_clang_tidy_extra.py │ │ ├── src/ │ │ │ ├── Acceptor.cpp │ │ │ ├── Buffer.cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── Channel.cpp │ │ │ ├── Connection.cpp │ │ │ ├── Epoll.cpp │ │ │ ├── EventLoop.cpp │ │ │ ├── Server.cpp │ │ │ ├── Socket.cpp │ │ │ ├── ThreadPool.cpp │ │ │ ├── include/ │ │ │ │ ├── Acceptor.h │ │ │ │ ├── Buffer.h │ │ │ │ ├── Channel.h │ │ │ │ ├── Connection.h │ │ │ │ ├── Epoll.h │ │ │ │ ├── EventLoop.h │ │ │ │ ├── Macros.h │ │ │ │ ├── Server.h │ │ │ │ ├── Socket.h │ │ │ │ ├── ThreadPool.h │ │ │ │ └── util.h │ │ │ └── util.cpp │ │ └── test/ │ │ ├── CMakeLists.txt │ │ ├── multiple_client.cpp │ │ ├── server.cpp │ │ ├── single_client.cpp │ │ └── thread_test.cpp │ ├── day15/ │ │ ├── .clang-format │ │ ├── .clang-tidy │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── build_support/ │ │ │ ├── clang_format_exclusions.txt │ │ │ ├── cpplint.py │ │ │ ├── run_clang_format.py │ │ │ ├── run_clang_tidy.py │ │ │ └── run_clang_tidy_extra.py │ │ ├── src/ │ │ │ ├── Acceptor.cpp │ │ │ ├── Buffer.cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── Channel.cpp │ │ │ ├── Connection.cpp │ │ │ ├── EventLoop.cpp │ │ │ ├── Poller.cpp │ │ │ ├── Server.cpp │ │ │ ├── Socket.cpp │ │ │ ├── ThreadPool.cpp │ │ │ ├── include/ │ │ │ │ ├── Acceptor.h │ │ │ │ ├── Buffer.h │ │ │ │ ├── Channel.h │ │ │ │ ├── Connection.h │ │ │ │ ├── EventLoop.h │ │ │ │ ├── Exception.h │ │ │ │ ├── Log.h │ │ │ │ ├── Macros.h │ │ │ │ ├── Poller.h │ │ │ │ ├── Server.h │ │ │ │ ├── SignalHandler.h │ │ │ │ ├── Socket.h │ │ │ │ ├── ThreadPool.h │ │ │ │ ├── pine.h │ │ │ │ └── util.h │ │ │ └── util.cpp │ │ └── test/ │ │ ├── CMakeLists.txt │ │ ├── chat_client.cpp │ │ ├── chat_server.cpp │ │ ├── echo_client.cpp │ │ ├── echo_clients.cpp │ │ ├── echo_server.cpp │ │ └── http_server.cpp │ └── day16/ │ ├── .clang-format │ ├── .clang-tidy │ ├── .gitignore │ ├── CMakeLists.txt │ ├── build_support/ │ │ ├── clang_format_exclusions.txt │ │ ├── cpplint.py │ │ ├── run_clang_format.py │ │ ├── run_clang_tidy.py │ │ └── run_clang_tidy_extra.py │ ├── src/ │ │ ├── Acceptor.cpp │ │ ├── Buffer.cpp │ │ ├── CMakeLists.txt │ │ ├── Channel.cpp │ │ ├── Connection.cpp │ │ ├── EventLoop.cpp │ │ ├── Poller.cpp │ │ ├── Socket.cpp │ │ ├── TcpServer.cpp │ │ ├── ThreadPool.cpp │ │ └── include/ │ │ ├── Acceptor.h │ │ ├── Buffer.h │ │ ├── Channel.h │ │ ├── Connection.h │ │ ├── EventLoop.h │ │ ├── Exception.h │ │ ├── Log.h │ │ ├── Poller.h │ │ ├── SignalHandler.h │ │ ├── Socket.h │ │ ├── TcpServer.h │ │ ├── ThreadPool.h │ │ ├── common.h │ │ └── pine.h │ └── test/ │ ├── CMakeLists.txt │ ├── chat_client.cpp │ ├── chat_server.cpp │ ├── echo_client.cpp │ ├── echo_clients.cpp │ ├── echo_server.cpp │ └── http_server.cpp ├── day01-从一个最简单的socket开始.md ├── day02-不要放过任何一个错误.md ├── day03-高并发还得用epoll.md ├── day04-来看看我们的第一个类.md ├── day05-epoll高级用法-Channel登场.md ├── day06-服务器与事件驱动核心类登场.md ├── day07-为我们的服务器添加一个Acceptor.md ├── day08-一切皆是类,连TCP连接也不例外.md ├── day09-缓冲区-大作用.md ├── day10-加入线程池到服务器.md ├── day11-完善线程池,加入一个简单的测试程序.md ├── day12-将服务器改写为主从Reactor多线程模式.md ├── day13-C++工程化、代码分析、性能优化.md ├── day14-支持业务逻辑自定义、完善Connection类.md ├── day15-macOS支持、完善业务逻辑自定义.md └── day16-重构核心库、使用智能指针.md
SYMBOL INDEX (1090 symbols across 220 files)
FILE: code/day01/client.cpp
function main (line 13) | int main() {
FILE: code/day01/server.cpp
function main (line 6) | int main() {
FILE: code/day02/client.cpp
function main (line 9) | int main() {
FILE: code/day02/server.cpp
function main (line 8) | int main() {
FILE: code/day02/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day03/client.cpp
function main (line 10) | int main() {
FILE: code/day03/server.cpp
function setnonblocking (line 14) | void setnonblocking(int fd){
function main (line 18) | int main() {
FILE: code/day03/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day04/Epoll.cpp
type epoll_event (line 24) | struct epoll_event
FILE: code/day04/Epoll.h
function class (line 5) | class Epoll
FILE: code/day04/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day04/Socket.h
function class (line 4) | class Socket
FILE: code/day04/client.cpp
function main (line 10) | int main() {
FILE: code/day04/server.cpp
function setnonblocking (line 15) | void setnonblocking(int fd){
function main (line 20) | int main() {
function handleReadEvent (line 50) | void handleReadEvent(int sockfd){
FILE: code/day04/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day05/Channel.h
function class (line 5) | class Channel
FILE: code/day05/Epoll.cpp
type epoll_event (line 25) | struct epoll_event
type epoll_event (line 56) | struct epoll_event
FILE: code/day05/Epoll.h
function class (line 6) | class Epoll
FILE: code/day05/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day05/Socket.h
function class (line 4) | class Socket
FILE: code/day05/client.cpp
function main (line 10) | int main() {
FILE: code/day05/server.cpp
function setnonblocking (line 16) | void setnonblocking(int fd){
function main (line 21) | int main() {
function handleReadEvent (line 54) | void handleReadEvent(int sockfd){
FILE: code/day05/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day06/client.cpp
function main (line 10) | int main() {
FILE: code/day06/server.cpp
function main (line 4) | int main() {
FILE: code/day06/src/Channel.h
function class (line 5) | class Channel
FILE: code/day06/src/Epoll.cpp
type epoll_event (line 25) | struct epoll_event
type epoll_event (line 56) | struct epoll_event
FILE: code/day06/src/Epoll.h
function class (line 6) | class Epoll
FILE: code/day06/src/EventLoop.h
function class (line 4) | class EventLoop
FILE: code/day06/src/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day06/src/Server.h
function class (line 5) | class Server
FILE: code/day06/src/Socket.h
function class (line 4) | class Socket
FILE: code/day06/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day07/client.cpp
function main (line 10) | int main() {
FILE: code/day07/server.cpp
function main (line 4) | int main() {
FILE: code/day07/src/Acceptor.h
function class (line 8) | class Acceptor
FILE: code/day07/src/Channel.h
function class (line 5) | class Channel
FILE: code/day07/src/Epoll.cpp
type epoll_event (line 25) | struct epoll_event
type epoll_event (line 56) | struct epoll_event
FILE: code/day07/src/Epoll.h
function class (line 6) | class Epoll
FILE: code/day07/src/EventLoop.h
function class (line 4) | class EventLoop
FILE: code/day07/src/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day07/src/Server.h
function class (line 6) | class Server
FILE: code/day07/src/Socket.h
function class (line 4) | class Socket
FILE: code/day07/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day08/client.cpp
function main (line 10) | int main() {
FILE: code/day08/server.cpp
function main (line 4) | int main() {
FILE: code/day08/src/Acceptor.h
function class (line 7) | class Acceptor
FILE: code/day08/src/Channel.h
function class (line 5) | class Channel
FILE: code/day08/src/Connection.h
function class (line 7) | class Connection
FILE: code/day08/src/Epoll.cpp
type epoll_event (line 56) | struct epoll_event
FILE: code/day08/src/Epoll.h
function class (line 6) | class Epoll
FILE: code/day08/src/EventLoop.h
function class (line 5) | class EventLoop
FILE: code/day08/src/InetAddress.cpp
function sockaddr_in (line 22) | sockaddr_in InetAddress::getAddr(){
function socklen_t (line 25) | socklen_t InetAddress::getAddr_len(){
FILE: code/day08/src/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day08/src/Server.h
function class (line 8) | class Server
FILE: code/day08/src/Socket.cpp
type sockaddr_in (line 25) | struct sockaddr_in
type sockaddr_in (line 39) | struct sockaddr_in
FILE: code/day08/src/Socket.h
function class (line 4) | class Socket
FILE: code/day08/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day09/client.cpp
function main (line 11) | int main() {
FILE: code/day09/server.cpp
function main (line 4) | int main() {
FILE: code/day09/src/Acceptor.h
function class (line 7) | class Acceptor
FILE: code/day09/src/Buffer.h
function class (line 4) | class Buffer
FILE: code/day09/src/Channel.h
function class (line 5) | class Channel
FILE: code/day09/src/Connection.h
function class (line 8) | class Connection
FILE: code/day09/src/Epoll.cpp
type epoll_event (line 56) | struct epoll_event
FILE: code/day09/src/Epoll.h
function class (line 6) | class Epoll
FILE: code/day09/src/EventLoop.h
function class (line 5) | class EventLoop
FILE: code/day09/src/InetAddress.cpp
function sockaddr_in (line 22) | sockaddr_in InetAddress::getAddr(){
function socklen_t (line 25) | socklen_t InetAddress::getAddr_len(){
FILE: code/day09/src/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day09/src/Server.h
function class (line 8) | class Server
FILE: code/day09/src/Socket.cpp
type sockaddr_in (line 25) | struct sockaddr_in
type sockaddr_in (line 39) | struct sockaddr_in
type sockaddr_in (line 48) | struct sockaddr_in
FILE: code/day09/src/Socket.h
function class (line 4) | class Socket
FILE: code/day09/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day10/ThreadPoolTest.cpp
function print (line 5) | void print(int a, double b, const char *c, std::string d){
function test (line 9) | void test(){
function main (line 13) | int main(int argc, char const *argv[])
FILE: code/day10/client.cpp
function main (line 11) | int main() {
FILE: code/day10/server.cpp
function main (line 4) | int main() {
FILE: code/day10/src/Acceptor.h
function class (line 7) | class Acceptor
FILE: code/day10/src/Buffer.h
function class (line 4) | class Buffer
FILE: code/day10/src/Channel.h
function class (line 5) | class Channel
FILE: code/day10/src/Connection.h
function class (line 8) | class Connection
FILE: code/day10/src/Epoll.cpp
type epoll_event (line 56) | struct epoll_event
FILE: code/day10/src/Epoll.h
function class (line 6) | class Epoll
FILE: code/day10/src/EventLoop.h
function class (line 7) | class EventLoop
FILE: code/day10/src/InetAddress.cpp
function sockaddr_in (line 22) | sockaddr_in InetAddress::getAddr(){
function socklen_t (line 25) | socklen_t InetAddress::getAddr_len(){
FILE: code/day10/src/InetAddress.h
function class (line 4) | class InetAddress
FILE: code/day10/src/Server.h
function class (line 8) | class Server
FILE: code/day10/src/Socket.cpp
type sockaddr_in (line 25) | struct sockaddr_in
type sockaddr_in (line 39) | struct sockaddr_in
type sockaddr_in (line 48) | struct sockaddr_in
FILE: code/day10/src/Socket.h
function class (line 4) | class Socket
FILE: code/day10/src/ThreadPool.h
function class (line 9) | class ThreadPool
FILE: code/day10/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day11/ThreadPoolTest.cpp
function print (line 5) | void print(int a, double b, const char *c, std::string d){
function test (line 9) | void test(){
function main (line 13) | int main(int argc, char const *argv[])
FILE: code/day11/client.cpp
function main (line 11) | int main() {
FILE: code/day11/server.cpp
function main (line 4) | int main() {
FILE: code/day11/src/Acceptor.h
function class (line 13) | class Acceptor
FILE: code/day11/src/Buffer.h
function class (line 10) | class Buffer
FILE: code/day11/src/Channel.h
function class (line 11) | class Channel
FILE: code/day11/src/Connection.h
function class (line 14) | class Connection
FILE: code/day11/src/Epoll.cpp
type epoll_event (line 44) | struct epoll_event
FILE: code/day11/src/Epoll.h
function class (line 12) | class Epoll
FILE: code/day11/src/EventLoop.h
function class (line 19) | class EventLoop
FILE: code/day11/src/InetAddress.cpp
function sockaddr_in (line 27) | sockaddr_in InetAddress::getAddr(){
FILE: code/day11/src/InetAddress.h
function class (line 10) | class InetAddress
FILE: code/day11/src/Server.h
function class (line 13) | class Server
FILE: code/day11/src/Socket.cpp
type sockaddr_in (line 31) | struct sockaddr_in
type sockaddr_in (line 43) | struct sockaddr_in
type sockaddr_in (line 53) | struct sockaddr_in
FILE: code/day11/src/Socket.h
function class (line 11) | class Socket
FILE: code/day11/src/ThreadPool.h
function class (line 16) | class ThreadPool
function task (line 41) | auto task = std::make_shared< std::packaged_task<return_type()> >(
FILE: code/day11/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day11/test.cpp
function oneClient (line 13) | void oneClient(int msgs, int wait){
function main (line 55) | int main(int argc, char *argv[]) {
FILE: code/day12/ThreadPoolTest.cpp
function print (line 5) | void print(int a, double b, const char *c, std::string d){
function test (line 9) | void test(){
function main (line 13) | int main(int argc, char const *argv[])
FILE: code/day12/client.cpp
function main (line 10) | int main() {
FILE: code/day12/server.cpp
function main (line 4) | int main() {
FILE: code/day12/src/Acceptor.h
function class (line 13) | class Acceptor
FILE: code/day12/src/Buffer.h
function class (line 10) | class Buffer
FILE: code/day12/src/Channel.h
function class (line 11) | class Channel
FILE: code/day12/src/Connection.h
function class (line 13) | class Connection
FILE: code/day12/src/Epoll.cpp
type epoll_event (line 44) | struct epoll_event
FILE: code/day12/src/Epoll.h
function class (line 12) | class Epoll
FILE: code/day12/src/EventLoop.h
function class (line 18) | class EventLoop
FILE: code/day12/src/Server.h
function class (line 15) | class Server
FILE: code/day12/src/Socket.cpp
type sockaddr_in (line 32) | struct sockaddr_in
type sockaddr_in (line 46) | struct sockaddr_in
type sockaddr_in (line 72) | struct sockaddr_in
function sockaddr_in (line 125) | sockaddr_in InetAddress::getAddr(){
FILE: code/day12/src/Socket.h
function class (line 11) | class InetAddress
function class (line 26) | class Socket
FILE: code/day12/src/ThreadPool.h
function class (line 16) | class ThreadPool
function task (line 43) | auto task = std::make_shared< std::packaged_task<return_type()> >(
FILE: code/day12/src/util.cpp
function errif (line 5) | void errif(bool condition, const char *errmsg){
FILE: code/day12/test.cpp
function oneClient (line 12) | void oneClient(int msgs, int wait){
function main (line 55) | int main(int argc, char *argv[]) {
FILE: code/day13/build_support/cpplint.py
function unicode_escape_decode (line 673) | def unicode_escape_decode(x):
function ProcessHppHeadersOption (line 687) | def ProcessHppHeadersOption(val):
function IsHeaderExtension (line 694) | def IsHeaderExtension(file_extension):
function GetHeaderExtensions (line 697) | def GetHeaderExtensions():
function GetAllExtensions (line 706) | def GetAllExtensions():
function ProcessExtensionsOption (line 710) | def ProcessExtensionsOption(val):
function GetNonHeaderExtensions (line 720) | def GetNonHeaderExtensions():
function ParseNolintSuppressions (line 723) | def ParseNolintSuppressions(filename, raw_line, linenum, error):
function ProcessGlobalSuppresions (line 755) | def ProcessGlobalSuppresions(lines):
function ResetNolintSuppressions (line 773) | def ResetNolintSuppressions():
function IsErrorSuppressedByNolint (line 779) | def IsErrorSuppressedByNolint(category, linenum):
function Match (line 797) | def Match(pattern, s):
function ReplaceAll (line 807) | def ReplaceAll(pattern, rep, s):
function Search (line 825) | def Search(pattern, s):
function _IsSourceExtension (line 832) | def _IsSourceExtension(s):
class _IncludeState (line 837) | class _IncludeState(object):
method __init__ (line 872) | def __init__(self):
method FindHeader (line 878) | def FindHeader(self, header):
method ResetSection (line 893) | def ResetSection(self, directive):
method SetLastHeader (line 911) | def SetLastHeader(self, header_path):
method CanonicalizeAlphabeticalOrder (line 914) | def CanonicalizeAlphabeticalOrder(self, header_path):
method IsInAlphabeticalOrder (line 929) | def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
method CheckNextIncludeOrder (line 950) | def CheckNextIncludeOrder(self, header_type):
class _CppLintState (line 1004) | class _CppLintState(object):
method __init__ (line 1007) | def __init__(self):
method SetOutputFormat (line 1030) | def SetOutputFormat(self, output_format):
method SetQuiet (line 1034) | def SetQuiet(self, quiet):
method SetVerboseLevel (line 1040) | def SetVerboseLevel(self, level):
method SetCountingStyle (line 1046) | def SetCountingStyle(self, counting_style):
method SetFilters (line 1050) | def SetFilters(self, filters):
method AddFilters (line 1068) | def AddFilters(self, filters):
method BackupFilters (line 1079) | def BackupFilters(self):
method RestoreFilters (line 1083) | def RestoreFilters(self):
method ResetErrorCounts (line 1087) | def ResetErrorCounts(self):
method IncrementErrorCount (line 1092) | def IncrementErrorCount(self, category):
method PrintErrorCounts (line 1102) | def PrintErrorCounts(self):
method PrintInfo (line 1110) | def PrintInfo(self, message):
method PrintError (line 1114) | def PrintError(self, message):
method AddJUnitFailure (line 1120) | def AddJUnitFailure(self, filename, linenum, message, category, confid...
method FormatJUnitXML (line 1124) | def FormatJUnitXML(self):
function _OutputFormat (line 1171) | def _OutputFormat():
function _SetOutputFormat (line 1176) | def _SetOutputFormat(output_format):
function _Quiet (line 1180) | def _Quiet():
function _SetQuiet (line 1184) | def _SetQuiet(quiet):
function _VerboseLevel (line 1189) | def _VerboseLevel():
function _SetVerboseLevel (line 1194) | def _SetVerboseLevel(level):
function _SetCountingStyle (line 1199) | def _SetCountingStyle(level):
function _Filters (line 1204) | def _Filters():
function _SetFilters (line 1209) | def _SetFilters(filters):
function _AddFilters (line 1221) | def _AddFilters(filters):
function _BackupFilters (line 1233) | def _BackupFilters():
function _RestoreFilters (line 1237) | def _RestoreFilters():
class _FunctionState (line 1241) | class _FunctionState(object):
method __init__ (line 1247) | def __init__(self):
method Begin (line 1252) | def Begin(self, function_name):
method Count (line 1262) | def Count(self):
method Check (line 1267) | def Check(self, error, filename, linenum):
method End (line 1295) | def End(self):
class _IncludeError (line 1300) | class _IncludeError(Exception):
class FileInfo (line 1305) | class FileInfo(object):
method __init__ (line 1312) | def __init__(self, filename):
method FullName (line 1315) | def FullName(self):
method RepositoryName (line 1319) | def RepositoryName(self):
method Split (line 1379) | def Split(self):
method BaseName (line 1393) | def BaseName(self):
method Extension (line 1397) | def Extension(self):
method NoExtension (line 1401) | def NoExtension(self):
method IsSource (line 1405) | def IsSource(self):
function _ShouldPrintError (line 1410) | def _ShouldPrintError(category, confidence, linenum):
function Error (line 1438) | def Error(filename, linenum, category, confidence, message):
function IsCppString (line 1496) | def IsCppString(line):
function CleanseRawStrings (line 1513) | def CleanseRawStrings(raw_lines):
function FindNextMultiLineCommentStart (line 1589) | def FindNextMultiLineCommentStart(lines, lineix):
function FindNextMultiLineCommentEnd (line 1600) | def FindNextMultiLineCommentEnd(lines, lineix):
function RemoveMultiLineCommentsFromRange (line 1609) | def RemoveMultiLineCommentsFromRange(lines, begin, end):
function RemoveMultiLineComments (line 1617) | def RemoveMultiLineComments(filename, lines, error):
function CleanseComments (line 1633) | def CleanseComments(line):
class CleansedLines (line 1649) | class CleansedLines(object):
method __init__ (line 1660) | def __init__(self, lines):
method NumLines (line 1672) | def NumLines(self):
method _CollapseStrings (line 1677) | def _CollapseStrings(elided):
function FindEndOfExpressionInLine (line 1744) | def FindEndOfExpressionInLine(line, startpos, stack):
function CloseExpression (line 1822) | def CloseExpression(clean_lines, linenum, pos):
function FindStartOfExpressionInLine (line 1866) | def FindStartOfExpressionInLine(line, endpos, stack):
function ReverseCloseExpression (line 1943) | def ReverseCloseExpression(clean_lines, linenum, pos):
function CheckForCopyright (line 1981) | def CheckForCopyright(filename, lines, error):
function GetIndentLevel (line 1994) | def GetIndentLevel(line):
function PathSplitToList (line 2009) | def PathSplitToList(path):
function GetHeaderGuardCPPVariable (line 2034) | def GetHeaderGuardCPPVariable(filename):
function CheckForHeaderGuard (line 2110) | def CheckForHeaderGuard(filename, clean_lines, error):
function CheckHeaderFileIncluded (line 2213) | def CheckHeaderFileIncluded(filename, include_state, error):
function CheckForBadCharacters (line 2240) | def CheckForBadCharacters(filename, lines, error):
function CheckForNewlineAtEOF (line 2265) | def CheckForNewlineAtEOF(filename, lines, error):
function CheckForMultilineCommentsAndStrings (line 2283) | def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, ...
function CheckPosixThreading (line 2351) | def CheckPosixThreading(filename, clean_lines, linenum, error):
function CheckVlogArguments (line 2377) | def CheckVlogArguments(filename, clean_lines, linenum, error):
function CheckInvalidIncrement (line 2401) | def CheckInvalidIncrement(filename, clean_lines, linenum, error):
function IsMacroDefinition (line 2423) | def IsMacroDefinition(clean_lines, linenum):
function IsForwardClassDeclaration (line 2433) | def IsForwardClassDeclaration(clean_lines, linenum):
class _BlockInfo (line 2437) | class _BlockInfo(object):
method __init__ (line 2440) | def __init__(self, linenum, seen_open_brace):
method CheckBegin (line 2447) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2462) | def CheckEnd(self, filename, clean_lines, linenum, error):
method IsBlockInfo (line 2475) | def IsBlockInfo(self):
class _ExternCInfo (line 2487) | class _ExternCInfo(_BlockInfo):
method __init__ (line 2490) | def __init__(self, linenum):
class _ClassInfo (line 2494) | class _ClassInfo(_BlockInfo):
method __init__ (line 2497) | def __init__(self, name, class_or_struct, clean_lines, linenum):
method CheckBegin (line 2527) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2532) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _NamespaceInfo (line 2563) | class _NamespaceInfo(_BlockInfo):
method __init__ (line 2566) | def __init__(self, name, linenum):
method CheckEnd (line 2571) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _PreprocessorInfo (line 2624) | class _PreprocessorInfo(object):
method __init__ (line 2627) | def __init__(self, stack_before_if):
class NestingState (line 2638) | class NestingState(object):
method __init__ (line 2641) | def __init__(self):
method SeenOpenBrace (line 2664) | def SeenOpenBrace(self):
method InNamespaceBody (line 2673) | def InNamespaceBody(self):
method InExternC (line 2681) | def InExternC(self):
method InClassDeclaration (line 2689) | def InClassDeclaration(self):
method InAsmBlock (line 2697) | def InAsmBlock(self):
method InTemplateArgumentList (line 2705) | def InTemplateArgumentList(self, clean_lines, linenum, pos):
method UpdatePreprocessor (line 2757) | def UpdatePreprocessor(self, line):
method Update (line 2814) | def Update(self, filename, clean_lines, linenum, error):
method InnermostClass (line 2978) | def InnermostClass(self):
method CheckCompletedBlocks (line 2990) | def CheckCompletedBlocks(self, filename, error):
function CheckForNonStandardConstructs (line 3012) | def CheckForNonStandardConstructs(filename, clean_lines, linenum,
function CheckSpacingForFunctionCall (line 3176) | def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
function IsBlankLine (line 3253) | def IsBlankLine(line):
function CheckForNamespaceIndentation (line 3268) | def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, l...
function CheckForFunctionLengths (line 3282) | def CheckForFunctionLengths(filename, clean_lines, linenum,
function CheckComment (line 3353) | def CheckComment(line, filename, linenum, next_line_start, error):
function CheckSpacing (line 3407) | def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
function CheckOperatorSpacing (line 3535) | def CheckOperatorSpacing(filename, clean_lines, linenum, error):
function CheckParenthesisSpacing (line 3650) | def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
function CheckCommaSpacing (line 3688) | def CheckCommaSpacing(filename, clean_lines, linenum, error):
function _IsType (line 3724) | def _IsType(clean_lines, nesting_state, expr):
function CheckBracesSpacing (line 3787) | def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, er...
function IsDecltype (line 3876) | def IsDecltype(clean_lines, linenum, column):
function CheckSectionSpacing (line 3893) | def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
function GetPreviousNonBlankLine (line 3948) | def GetPreviousNonBlankLine(clean_lines, linenum):
function CheckBraces (line 3971) | def CheckBraces(filename, clean_lines, linenum, error):
function CheckTrailingSemicolon (line 4090) | def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
function CheckEmptyBlockBody (line 4237) | def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
function FindCheckMacro (line 4341) | def FindCheckMacro(line):
function CheckCheck (line 4364) | def CheckCheck(filename, clean_lines, linenum, error):
function CheckAltTokens (line 4482) | def CheckAltTokens(filename, clean_lines, linenum, error):
function GetLineWidth (line 4514) | def GetLineWidth(line):
function CheckStyle (line 4546) | def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_s...
function _DropCommonSuffixes (line 4681) | def _DropCommonSuffixes(filename):
function _ClassifyInclude (line 4711) | def _ClassifyInclude(fileinfo, include, is_system):
function CheckIncludeLine (line 4777) | def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
function _GetTextInside (line 4868) | def _GetTextInside(text, start_pattern):
function CheckLanguage (line 4953) | def CheckLanguage(filename, clean_lines, linenum, file_extension,
function CheckGlobalStatic (line 5114) | def CheckGlobalStatic(filename, clean_lines, linenum, error):
function CheckPrintf (line 5175) | def CheckPrintf(filename, clean_lines, linenum, error):
function IsDerivedFunction (line 5204) | def IsDerivedFunction(clean_lines, linenum):
function IsOutOfLineMethodDefinition (line 5226) | def IsOutOfLineMethodDefinition(clean_lines, linenum):
function IsInitializerList (line 5242) | def IsInitializerList(clean_lines, linenum):
function CheckForNonConstReference (line 5284) | def CheckForNonConstReference(filename, clean_lines, linenum,
function CheckCasts (line 5423) | def CheckCasts(filename, clean_lines, linenum, error):
function CheckCStyleCast (line 5542) | def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, ...
function ExpectingFunctionArgs (line 5595) | def ExpectingFunctionArgs(clean_lines, linenum):
function FilesBelongToSameModule (line 5697) | def FilesBelongToSameModule(filename_cc, filename_h):
function UpdateIncludeState (line 5755) | def UpdateIncludeState(filename, include_dict, io=codecs):
function CheckForIncludeWhatYouUse (line 5782) | def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
function CheckMakePairUsesDeduction (line 5886) | def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
function CheckRedundantVirtual (line 5907) | def CheckRedundantVirtual(filename, clean_lines, linenum, error):
function CheckRedundantOverrideOrFinal (line 5971) | def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
function IsBlockInNameSpace (line 6004) | def IsBlockInNameSpace(nesting_state, is_forward_declaration):
function ShouldCheckNamespaceIndentation (line 6023) | def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_i...
function CheckItemIndentationInNamespace (line 6056) | def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, lin...
function ProcessLine (line 6064) | def ProcessLine(filename, file_extension, clean_lines, line,
function FlagCxx11Features (line 6109) | def FlagCxx11Features(filename, clean_lines, linenum, error):
function FlagCxx14Features (line 6161) | def FlagCxx14Features(filename, clean_lines, linenum, error):
function ProcessFileData (line 6180) | def ProcessFileData(filename, file_extension, lines, error,
function ProcessConfigOverrides (line 6231) | def ProcessConfigOverrides(filename):
function ProcessFile (line 6318) | def ProcessFile(filename, vlevel, extra_check_functions=None):
function PrintUsage (line 6410) | def PrintUsage(message):
function PrintVersion (line 6426) | def PrintVersion():
function PrintCategories (line 6432) | def PrintCategories():
function ParseArguments (line 6441) | def ParseArguments(args):
function _ExpandDirectories (line 6539) | def _ExpandDirectories(filenames):
function _FilterExcludedFiles (line 6571) | def _FilterExcludedFiles(filenames):
function main (line 6578) | def main():
FILE: code/day13/build_support/run_clang_format.py
function check (line 30) | def check(arguments, source_dir):
FILE: code/day13/build_support/run_clang_tidy.py
function find_compilation_database (line 60) | def find_compilation_database(path):
function make_absolute (line 71) | def make_absolute(f, directory):
function get_tidy_invocation (line 77) | def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path,
function merge_replacement_files (line 110) | def merge_replacement_files(tmpdir, mergefile):
function check_clang_apply_replacements_binary (line 134) | def check_clang_apply_replacements_binary(args):
function apply_fixes (line 145) | def apply_fixes(args, tmpdir):
function run_tidy (line 156) | def run_tidy(args, tmpdir, build_path, queue, lock, failed_files):
function main (line 193) | def main():
FILE: code/day13/build_support/run_clang_tidy_extra.py
class CheckConfig (line 17) | class CheckConfig(object):
method __init__ (line 20) | def __init__(self):
method _init_config (line 26) | def _init_config(self):
method should_skip (line 33) | def should_skip(self, path):
FILE: code/day13/src/Epoll.cpp
type epoll_event (line 51) | struct epoll_event
FILE: code/day13/src/Socket.cpp
type sockaddr_in (line 37) | struct sockaddr_in
type sockaddr_in (line 47) | struct sockaddr_in
type sockaddr_in (line 72) | struct sockaddr_in
function sockaddr_in (line 116) | sockaddr_in InetAddress::GetAddr() { return addr_; }
FILE: code/day13/src/include/Acceptor.h
function class (line 19) | class Acceptor {
FILE: code/day13/src/include/Buffer.h
function class (line 15) | class Buffer {
FILE: code/day13/src/include/Channel.h
function class (line 18) | class Channel {
FILE: code/day13/src/include/Connection.h
function class (line 20) | class Connection {
FILE: code/day13/src/include/Epoll.h
function class (line 21) | class Epoll {
FILE: code/day13/src/include/EventLoop.h
function class (line 18) | class EventLoop {
FILE: code/day13/src/include/Server.h
function class (line 21) | class Server {
FILE: code/day13/src/include/Socket.h
function class (line 16) | class InetAddress {
function class (line 33) | class Socket {
FILE: code/day13/src/include/ThreadPool.h
function class (line 23) | class ThreadPool {
FILE: code/day13/src/util.cpp
function ErrorIf (line 16) | void ErrorIf(bool condition, const char *errmsg) {
FILE: code/day13/test/multiple_client.cpp
function OneClient (line 12) | void OneClient(int msgs, int wait) {
function main (line 57) | int main(int argc, char *argv[]) {
FILE: code/day13/test/server.cpp
function main (line 5) | int main() {
FILE: code/day13/test/single_client.cpp
function main (line 10) | int main() {
FILE: code/day13/test/thread_test.cpp
function Print (line 6) | void Print(int a, double b, const char *c, std::string const &d) { std::...
function Test (line 8) | void Test() { std::cout << "hellp" << std::endl; }
function main (line 10) | int main(int argc, char const *argv[]) {
FILE: code/day14/build_support/cpplint.py
function unicode_escape_decode (line 673) | def unicode_escape_decode(x):
function ProcessHppHeadersOption (line 687) | def ProcessHppHeadersOption(val):
function IsHeaderExtension (line 694) | def IsHeaderExtension(file_extension):
function GetHeaderExtensions (line 697) | def GetHeaderExtensions():
function GetAllExtensions (line 706) | def GetAllExtensions():
function ProcessExtensionsOption (line 710) | def ProcessExtensionsOption(val):
function GetNonHeaderExtensions (line 720) | def GetNonHeaderExtensions():
function ParseNolintSuppressions (line 723) | def ParseNolintSuppressions(filename, raw_line, linenum, error):
function ProcessGlobalSuppresions (line 755) | def ProcessGlobalSuppresions(lines):
function ResetNolintSuppressions (line 773) | def ResetNolintSuppressions():
function IsErrorSuppressedByNolint (line 779) | def IsErrorSuppressedByNolint(category, linenum):
function Match (line 797) | def Match(pattern, s):
function ReplaceAll (line 807) | def ReplaceAll(pattern, rep, s):
function Search (line 825) | def Search(pattern, s):
function _IsSourceExtension (line 832) | def _IsSourceExtension(s):
class _IncludeState (line 837) | class _IncludeState(object):
method __init__ (line 872) | def __init__(self):
method FindHeader (line 878) | def FindHeader(self, header):
method ResetSection (line 893) | def ResetSection(self, directive):
method SetLastHeader (line 911) | def SetLastHeader(self, header_path):
method CanonicalizeAlphabeticalOrder (line 914) | def CanonicalizeAlphabeticalOrder(self, header_path):
method IsInAlphabeticalOrder (line 929) | def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
method CheckNextIncludeOrder (line 950) | def CheckNextIncludeOrder(self, header_type):
class _CppLintState (line 1004) | class _CppLintState(object):
method __init__ (line 1007) | def __init__(self):
method SetOutputFormat (line 1030) | def SetOutputFormat(self, output_format):
method SetQuiet (line 1034) | def SetQuiet(self, quiet):
method SetVerboseLevel (line 1040) | def SetVerboseLevel(self, level):
method SetCountingStyle (line 1046) | def SetCountingStyle(self, counting_style):
method SetFilters (line 1050) | def SetFilters(self, filters):
method AddFilters (line 1068) | def AddFilters(self, filters):
method BackupFilters (line 1079) | def BackupFilters(self):
method RestoreFilters (line 1083) | def RestoreFilters(self):
method ResetErrorCounts (line 1087) | def ResetErrorCounts(self):
method IncrementErrorCount (line 1092) | def IncrementErrorCount(self, category):
method PrintErrorCounts (line 1102) | def PrintErrorCounts(self):
method PrintInfo (line 1110) | def PrintInfo(self, message):
method PrintError (line 1114) | def PrintError(self, message):
method AddJUnitFailure (line 1120) | def AddJUnitFailure(self, filename, linenum, message, category, confid...
method FormatJUnitXML (line 1124) | def FormatJUnitXML(self):
function _OutputFormat (line 1171) | def _OutputFormat():
function _SetOutputFormat (line 1176) | def _SetOutputFormat(output_format):
function _Quiet (line 1180) | def _Quiet():
function _SetQuiet (line 1184) | def _SetQuiet(quiet):
function _VerboseLevel (line 1189) | def _VerboseLevel():
function _SetVerboseLevel (line 1194) | def _SetVerboseLevel(level):
function _SetCountingStyle (line 1199) | def _SetCountingStyle(level):
function _Filters (line 1204) | def _Filters():
function _SetFilters (line 1209) | def _SetFilters(filters):
function _AddFilters (line 1221) | def _AddFilters(filters):
function _BackupFilters (line 1233) | def _BackupFilters():
function _RestoreFilters (line 1237) | def _RestoreFilters():
class _FunctionState (line 1241) | class _FunctionState(object):
method __init__ (line 1247) | def __init__(self):
method Begin (line 1252) | def Begin(self, function_name):
method Count (line 1262) | def Count(self):
method Check (line 1267) | def Check(self, error, filename, linenum):
method End (line 1295) | def End(self):
class _IncludeError (line 1300) | class _IncludeError(Exception):
class FileInfo (line 1305) | class FileInfo(object):
method __init__ (line 1312) | def __init__(self, filename):
method FullName (line 1315) | def FullName(self):
method RepositoryName (line 1319) | def RepositoryName(self):
method Split (line 1379) | def Split(self):
method BaseName (line 1393) | def BaseName(self):
method Extension (line 1397) | def Extension(self):
method NoExtension (line 1401) | def NoExtension(self):
method IsSource (line 1405) | def IsSource(self):
function _ShouldPrintError (line 1410) | def _ShouldPrintError(category, confidence, linenum):
function Error (line 1438) | def Error(filename, linenum, category, confidence, message):
function IsCppString (line 1496) | def IsCppString(line):
function CleanseRawStrings (line 1513) | def CleanseRawStrings(raw_lines):
function FindNextMultiLineCommentStart (line 1589) | def FindNextMultiLineCommentStart(lines, lineix):
function FindNextMultiLineCommentEnd (line 1600) | def FindNextMultiLineCommentEnd(lines, lineix):
function RemoveMultiLineCommentsFromRange (line 1609) | def RemoveMultiLineCommentsFromRange(lines, begin, end):
function RemoveMultiLineComments (line 1617) | def RemoveMultiLineComments(filename, lines, error):
function CleanseComments (line 1633) | def CleanseComments(line):
class CleansedLines (line 1649) | class CleansedLines(object):
method __init__ (line 1660) | def __init__(self, lines):
method NumLines (line 1672) | def NumLines(self):
method _CollapseStrings (line 1677) | def _CollapseStrings(elided):
function FindEndOfExpressionInLine (line 1744) | def FindEndOfExpressionInLine(line, startpos, stack):
function CloseExpression (line 1822) | def CloseExpression(clean_lines, linenum, pos):
function FindStartOfExpressionInLine (line 1866) | def FindStartOfExpressionInLine(line, endpos, stack):
function ReverseCloseExpression (line 1943) | def ReverseCloseExpression(clean_lines, linenum, pos):
function CheckForCopyright (line 1981) | def CheckForCopyright(filename, lines, error):
function GetIndentLevel (line 1994) | def GetIndentLevel(line):
function PathSplitToList (line 2009) | def PathSplitToList(path):
function GetHeaderGuardCPPVariable (line 2034) | def GetHeaderGuardCPPVariable(filename):
function CheckForHeaderGuard (line 2110) | def CheckForHeaderGuard(filename, clean_lines, error):
function CheckHeaderFileIncluded (line 2213) | def CheckHeaderFileIncluded(filename, include_state, error):
function CheckForBadCharacters (line 2240) | def CheckForBadCharacters(filename, lines, error):
function CheckForNewlineAtEOF (line 2265) | def CheckForNewlineAtEOF(filename, lines, error):
function CheckForMultilineCommentsAndStrings (line 2283) | def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, ...
function CheckPosixThreading (line 2351) | def CheckPosixThreading(filename, clean_lines, linenum, error):
function CheckVlogArguments (line 2377) | def CheckVlogArguments(filename, clean_lines, linenum, error):
function CheckInvalidIncrement (line 2401) | def CheckInvalidIncrement(filename, clean_lines, linenum, error):
function IsMacroDefinition (line 2423) | def IsMacroDefinition(clean_lines, linenum):
function IsForwardClassDeclaration (line 2433) | def IsForwardClassDeclaration(clean_lines, linenum):
class _BlockInfo (line 2437) | class _BlockInfo(object):
method __init__ (line 2440) | def __init__(self, linenum, seen_open_brace):
method CheckBegin (line 2447) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2462) | def CheckEnd(self, filename, clean_lines, linenum, error):
method IsBlockInfo (line 2475) | def IsBlockInfo(self):
class _ExternCInfo (line 2487) | class _ExternCInfo(_BlockInfo):
method __init__ (line 2490) | def __init__(self, linenum):
class _ClassInfo (line 2494) | class _ClassInfo(_BlockInfo):
method __init__ (line 2497) | def __init__(self, name, class_or_struct, clean_lines, linenum):
method CheckBegin (line 2527) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2532) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _NamespaceInfo (line 2563) | class _NamespaceInfo(_BlockInfo):
method __init__ (line 2566) | def __init__(self, name, linenum):
method CheckEnd (line 2571) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _PreprocessorInfo (line 2624) | class _PreprocessorInfo(object):
method __init__ (line 2627) | def __init__(self, stack_before_if):
class NestingState (line 2638) | class NestingState(object):
method __init__ (line 2641) | def __init__(self):
method SeenOpenBrace (line 2664) | def SeenOpenBrace(self):
method InNamespaceBody (line 2673) | def InNamespaceBody(self):
method InExternC (line 2681) | def InExternC(self):
method InClassDeclaration (line 2689) | def InClassDeclaration(self):
method InAsmBlock (line 2697) | def InAsmBlock(self):
method InTemplateArgumentList (line 2705) | def InTemplateArgumentList(self, clean_lines, linenum, pos):
method UpdatePreprocessor (line 2757) | def UpdatePreprocessor(self, line):
method Update (line 2814) | def Update(self, filename, clean_lines, linenum, error):
method InnermostClass (line 2978) | def InnermostClass(self):
method CheckCompletedBlocks (line 2990) | def CheckCompletedBlocks(self, filename, error):
function CheckForNonStandardConstructs (line 3012) | def CheckForNonStandardConstructs(filename, clean_lines, linenum,
function CheckSpacingForFunctionCall (line 3176) | def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
function IsBlankLine (line 3253) | def IsBlankLine(line):
function CheckForNamespaceIndentation (line 3268) | def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, l...
function CheckForFunctionLengths (line 3282) | def CheckForFunctionLengths(filename, clean_lines, linenum,
function CheckComment (line 3353) | def CheckComment(line, filename, linenum, next_line_start, error):
function CheckSpacing (line 3407) | def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
function CheckOperatorSpacing (line 3535) | def CheckOperatorSpacing(filename, clean_lines, linenum, error):
function CheckParenthesisSpacing (line 3650) | def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
function CheckCommaSpacing (line 3688) | def CheckCommaSpacing(filename, clean_lines, linenum, error):
function _IsType (line 3724) | def _IsType(clean_lines, nesting_state, expr):
function CheckBracesSpacing (line 3787) | def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, er...
function IsDecltype (line 3876) | def IsDecltype(clean_lines, linenum, column):
function CheckSectionSpacing (line 3893) | def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
function GetPreviousNonBlankLine (line 3948) | def GetPreviousNonBlankLine(clean_lines, linenum):
function CheckBraces (line 3971) | def CheckBraces(filename, clean_lines, linenum, error):
function CheckTrailingSemicolon (line 4090) | def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
function CheckEmptyBlockBody (line 4237) | def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
function FindCheckMacro (line 4341) | def FindCheckMacro(line):
function CheckCheck (line 4364) | def CheckCheck(filename, clean_lines, linenum, error):
function CheckAltTokens (line 4482) | def CheckAltTokens(filename, clean_lines, linenum, error):
function GetLineWidth (line 4514) | def GetLineWidth(line):
function CheckStyle (line 4546) | def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_s...
function _DropCommonSuffixes (line 4681) | def _DropCommonSuffixes(filename):
function _ClassifyInclude (line 4711) | def _ClassifyInclude(fileinfo, include, is_system):
function CheckIncludeLine (line 4777) | def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
function _GetTextInside (line 4868) | def _GetTextInside(text, start_pattern):
function CheckLanguage (line 4953) | def CheckLanguage(filename, clean_lines, linenum, file_extension,
function CheckGlobalStatic (line 5114) | def CheckGlobalStatic(filename, clean_lines, linenum, error):
function CheckPrintf (line 5175) | def CheckPrintf(filename, clean_lines, linenum, error):
function IsDerivedFunction (line 5204) | def IsDerivedFunction(clean_lines, linenum):
function IsOutOfLineMethodDefinition (line 5226) | def IsOutOfLineMethodDefinition(clean_lines, linenum):
function IsInitializerList (line 5242) | def IsInitializerList(clean_lines, linenum):
function CheckForNonConstReference (line 5284) | def CheckForNonConstReference(filename, clean_lines, linenum,
function CheckCasts (line 5423) | def CheckCasts(filename, clean_lines, linenum, error):
function CheckCStyleCast (line 5542) | def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, ...
function ExpectingFunctionArgs (line 5595) | def ExpectingFunctionArgs(clean_lines, linenum):
function FilesBelongToSameModule (line 5697) | def FilesBelongToSameModule(filename_cc, filename_h):
function UpdateIncludeState (line 5755) | def UpdateIncludeState(filename, include_dict, io=codecs):
function CheckForIncludeWhatYouUse (line 5782) | def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
function CheckMakePairUsesDeduction (line 5886) | def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
function CheckRedundantVirtual (line 5907) | def CheckRedundantVirtual(filename, clean_lines, linenum, error):
function CheckRedundantOverrideOrFinal (line 5971) | def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
function IsBlockInNameSpace (line 6004) | def IsBlockInNameSpace(nesting_state, is_forward_declaration):
function ShouldCheckNamespaceIndentation (line 6023) | def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_i...
function CheckItemIndentationInNamespace (line 6056) | def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, lin...
function ProcessLine (line 6064) | def ProcessLine(filename, file_extension, clean_lines, line,
function FlagCxx11Features (line 6109) | def FlagCxx11Features(filename, clean_lines, linenum, error):
function FlagCxx14Features (line 6161) | def FlagCxx14Features(filename, clean_lines, linenum, error):
function ProcessFileData (line 6180) | def ProcessFileData(filename, file_extension, lines, error,
function ProcessConfigOverrides (line 6231) | def ProcessConfigOverrides(filename):
function ProcessFile (line 6318) | def ProcessFile(filename, vlevel, extra_check_functions=None):
function PrintUsage (line 6410) | def PrintUsage(message):
function PrintVersion (line 6426) | def PrintVersion():
function PrintCategories (line 6432) | def PrintCategories():
function ParseArguments (line 6441) | def ParseArguments(args):
function _ExpandDirectories (line 6539) | def _ExpandDirectories(filenames):
function _FilterExcludedFiles (line 6571) | def _FilterExcludedFiles(filenames):
function main (line 6578) | def main():
FILE: code/day14/build_support/run_clang_format.py
function check (line 30) | def check(arguments, source_dir):
FILE: code/day14/build_support/run_clang_tidy.py
function find_compilation_database (line 60) | def find_compilation_database(path):
function make_absolute (line 71) | def make_absolute(f, directory):
function get_tidy_invocation (line 77) | def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path,
function merge_replacement_files (line 110) | def merge_replacement_files(tmpdir, mergefile):
function check_clang_apply_replacements_binary (line 134) | def check_clang_apply_replacements_binary(args):
function apply_fixes (line 145) | def apply_fixes(args, tmpdir):
function run_tidy (line 156) | def run_tidy(args, tmpdir, build_path, queue, lock, failed_files):
function main (line 193) | def main():
FILE: code/day14/build_support/run_clang_tidy_extra.py
class CheckConfig (line 17) | class CheckConfig(object):
method __init__ (line 20) | def __init__(self):
method _init_config (line 26) | def _init_config(self):
method should_skip (line 33) | def should_skip(self, path):
FILE: code/day14/src/Connection.cpp
function Buffer (line 152) | Buffer *Connection::GetReadBuffer() { return read_buffer_; }
function Buffer (line 154) | Buffer *Connection::GetSendBuffer() { return send_buffer_; }
function Socket (line 167) | Socket *Connection::GetSocket() { return sock_; }
FILE: code/day14/src/Epoll.cpp
type epoll_event (line 51) | struct epoll_event
FILE: code/day14/src/Socket.cpp
type sockaddr_in (line 37) | struct sockaddr_in
type sockaddr_in (line 47) | struct sockaddr_in
type sockaddr_in (line 72) | struct sockaddr_in
function sockaddr_in (line 122) | sockaddr_in InetAddress::GetAddr() { return addr_; }
FILE: code/day14/src/include/Acceptor.h
function class (line 19) | class Acceptor {
FILE: code/day14/src/include/Buffer.h
function class (line 15) | class Buffer {
FILE: code/day14/src/include/Channel.h
function class (line 18) | class Channel {
FILE: code/day14/src/include/Connection.h
type State (line 22) | enum State {
function Buffer (line 56) | Buffer *send_buffer_{nullptr};
FILE: code/day14/src/include/Epoll.h
function class (line 21) | class Epoll {
FILE: code/day14/src/include/EventLoop.h
function class (line 18) | class EventLoop {
FILE: code/day14/src/include/Server.h
function class (line 22) | class Server {
FILE: code/day14/src/include/Socket.h
function class (line 16) | class InetAddress {
function class (line 33) | class Socket {
FILE: code/day14/src/include/ThreadPool.h
function class (line 23) | class ThreadPool {
FILE: code/day14/src/util.cpp
function ErrorIf (line 16) | void ErrorIf(bool condition, const char *errmsg) {
FILE: code/day14/test/multiple_client.cpp
function OneClient (line 11) | void OneClient(int msgs, int wait) {
function main (line 30) | int main(int argc, char *argv[]) {
FILE: code/day14/test/server.cpp
function main (line 8) | int main() {
FILE: code/day14/test/single_client.cpp
function main (line 5) | int main() {
FILE: code/day14/test/thread_test.cpp
function Print (line 6) | void Print(int a, double b, const char *c, std::string const &d) { std::...
function Test (line 8) | void Test() { std::cout << "hellp" << std::endl; }
function main (line 10) | int main(int argc, char const *argv[]) {
FILE: code/day15/build_support/cpplint.py
function unicode_escape_decode (line 673) | def unicode_escape_decode(x):
function ProcessHppHeadersOption (line 687) | def ProcessHppHeadersOption(val):
function IsHeaderExtension (line 694) | def IsHeaderExtension(file_extension):
function GetHeaderExtensions (line 697) | def GetHeaderExtensions():
function GetAllExtensions (line 706) | def GetAllExtensions():
function ProcessExtensionsOption (line 710) | def ProcessExtensionsOption(val):
function GetNonHeaderExtensions (line 720) | def GetNonHeaderExtensions():
function ParseNolintSuppressions (line 723) | def ParseNolintSuppressions(filename, raw_line, linenum, error):
function ProcessGlobalSuppresions (line 755) | def ProcessGlobalSuppresions(lines):
function ResetNolintSuppressions (line 773) | def ResetNolintSuppressions():
function IsErrorSuppressedByNolint (line 779) | def IsErrorSuppressedByNolint(category, linenum):
function Match (line 797) | def Match(pattern, s):
function ReplaceAll (line 807) | def ReplaceAll(pattern, rep, s):
function Search (line 825) | def Search(pattern, s):
function _IsSourceExtension (line 832) | def _IsSourceExtension(s):
class _IncludeState (line 837) | class _IncludeState(object):
method __init__ (line 872) | def __init__(self):
method FindHeader (line 878) | def FindHeader(self, header):
method ResetSection (line 893) | def ResetSection(self, directive):
method SetLastHeader (line 911) | def SetLastHeader(self, header_path):
method CanonicalizeAlphabeticalOrder (line 914) | def CanonicalizeAlphabeticalOrder(self, header_path):
method IsInAlphabeticalOrder (line 929) | def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
method CheckNextIncludeOrder (line 950) | def CheckNextIncludeOrder(self, header_type):
class _CppLintState (line 1004) | class _CppLintState(object):
method __init__ (line 1007) | def __init__(self):
method SetOutputFormat (line 1030) | def SetOutputFormat(self, output_format):
method SetQuiet (line 1034) | def SetQuiet(self, quiet):
method SetVerboseLevel (line 1040) | def SetVerboseLevel(self, level):
method SetCountingStyle (line 1046) | def SetCountingStyle(self, counting_style):
method SetFilters (line 1050) | def SetFilters(self, filters):
method AddFilters (line 1068) | def AddFilters(self, filters):
method BackupFilters (line 1079) | def BackupFilters(self):
method RestoreFilters (line 1083) | def RestoreFilters(self):
method ResetErrorCounts (line 1087) | def ResetErrorCounts(self):
method IncrementErrorCount (line 1092) | def IncrementErrorCount(self, category):
method PrintErrorCounts (line 1102) | def PrintErrorCounts(self):
method PrintInfo (line 1110) | def PrintInfo(self, message):
method PrintError (line 1114) | def PrintError(self, message):
method AddJUnitFailure (line 1120) | def AddJUnitFailure(self, filename, linenum, message, category, confid...
method FormatJUnitXML (line 1124) | def FormatJUnitXML(self):
function _OutputFormat (line 1171) | def _OutputFormat():
function _SetOutputFormat (line 1176) | def _SetOutputFormat(output_format):
function _Quiet (line 1180) | def _Quiet():
function _SetQuiet (line 1184) | def _SetQuiet(quiet):
function _VerboseLevel (line 1189) | def _VerboseLevel():
function _SetVerboseLevel (line 1194) | def _SetVerboseLevel(level):
function _SetCountingStyle (line 1199) | def _SetCountingStyle(level):
function _Filters (line 1204) | def _Filters():
function _SetFilters (line 1209) | def _SetFilters(filters):
function _AddFilters (line 1221) | def _AddFilters(filters):
function _BackupFilters (line 1233) | def _BackupFilters():
function _RestoreFilters (line 1237) | def _RestoreFilters():
class _FunctionState (line 1241) | class _FunctionState(object):
method __init__ (line 1247) | def __init__(self):
method Begin (line 1252) | def Begin(self, function_name):
method Count (line 1262) | def Count(self):
method Check (line 1267) | def Check(self, error, filename, linenum):
method End (line 1295) | def End(self):
class _IncludeError (line 1300) | class _IncludeError(Exception):
class FileInfo (line 1305) | class FileInfo(object):
method __init__ (line 1312) | def __init__(self, filename):
method FullName (line 1315) | def FullName(self):
method RepositoryName (line 1319) | def RepositoryName(self):
method Split (line 1379) | def Split(self):
method BaseName (line 1393) | def BaseName(self):
method Extension (line 1397) | def Extension(self):
method NoExtension (line 1401) | def NoExtension(self):
method IsSource (line 1405) | def IsSource(self):
function _ShouldPrintError (line 1410) | def _ShouldPrintError(category, confidence, linenum):
function Error (line 1438) | def Error(filename, linenum, category, confidence, message):
function IsCppString (line 1496) | def IsCppString(line):
function CleanseRawStrings (line 1513) | def CleanseRawStrings(raw_lines):
function FindNextMultiLineCommentStart (line 1589) | def FindNextMultiLineCommentStart(lines, lineix):
function FindNextMultiLineCommentEnd (line 1600) | def FindNextMultiLineCommentEnd(lines, lineix):
function RemoveMultiLineCommentsFromRange (line 1609) | def RemoveMultiLineCommentsFromRange(lines, begin, end):
function RemoveMultiLineComments (line 1617) | def RemoveMultiLineComments(filename, lines, error):
function CleanseComments (line 1633) | def CleanseComments(line):
class CleansedLines (line 1649) | class CleansedLines(object):
method __init__ (line 1660) | def __init__(self, lines):
method NumLines (line 1672) | def NumLines(self):
method _CollapseStrings (line 1677) | def _CollapseStrings(elided):
function FindEndOfExpressionInLine (line 1744) | def FindEndOfExpressionInLine(line, startpos, stack):
function CloseExpression (line 1822) | def CloseExpression(clean_lines, linenum, pos):
function FindStartOfExpressionInLine (line 1866) | def FindStartOfExpressionInLine(line, endpos, stack):
function ReverseCloseExpression (line 1943) | def ReverseCloseExpression(clean_lines, linenum, pos):
function CheckForCopyright (line 1981) | def CheckForCopyright(filename, lines, error):
function GetIndentLevel (line 1994) | def GetIndentLevel(line):
function PathSplitToList (line 2009) | def PathSplitToList(path):
function GetHeaderGuardCPPVariable (line 2034) | def GetHeaderGuardCPPVariable(filename):
function CheckForHeaderGuard (line 2110) | def CheckForHeaderGuard(filename, clean_lines, error):
function CheckHeaderFileIncluded (line 2213) | def CheckHeaderFileIncluded(filename, include_state, error):
function CheckForBadCharacters (line 2240) | def CheckForBadCharacters(filename, lines, error):
function CheckForNewlineAtEOF (line 2265) | def CheckForNewlineAtEOF(filename, lines, error):
function CheckForMultilineCommentsAndStrings (line 2283) | def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, ...
function CheckPosixThreading (line 2351) | def CheckPosixThreading(filename, clean_lines, linenum, error):
function CheckVlogArguments (line 2377) | def CheckVlogArguments(filename, clean_lines, linenum, error):
function CheckInvalidIncrement (line 2401) | def CheckInvalidIncrement(filename, clean_lines, linenum, error):
function IsMacroDefinition (line 2423) | def IsMacroDefinition(clean_lines, linenum):
function IsForwardClassDeclaration (line 2433) | def IsForwardClassDeclaration(clean_lines, linenum):
class _BlockInfo (line 2437) | class _BlockInfo(object):
method __init__ (line 2440) | def __init__(self, linenum, seen_open_brace):
method CheckBegin (line 2447) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2462) | def CheckEnd(self, filename, clean_lines, linenum, error):
method IsBlockInfo (line 2475) | def IsBlockInfo(self):
class _ExternCInfo (line 2487) | class _ExternCInfo(_BlockInfo):
method __init__ (line 2490) | def __init__(self, linenum):
class _ClassInfo (line 2494) | class _ClassInfo(_BlockInfo):
method __init__ (line 2497) | def __init__(self, name, class_or_struct, clean_lines, linenum):
method CheckBegin (line 2527) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2532) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _NamespaceInfo (line 2563) | class _NamespaceInfo(_BlockInfo):
method __init__ (line 2566) | def __init__(self, name, linenum):
method CheckEnd (line 2571) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _PreprocessorInfo (line 2624) | class _PreprocessorInfo(object):
method __init__ (line 2627) | def __init__(self, stack_before_if):
class NestingState (line 2638) | class NestingState(object):
method __init__ (line 2641) | def __init__(self):
method SeenOpenBrace (line 2664) | def SeenOpenBrace(self):
method InNamespaceBody (line 2673) | def InNamespaceBody(self):
method InExternC (line 2681) | def InExternC(self):
method InClassDeclaration (line 2689) | def InClassDeclaration(self):
method InAsmBlock (line 2697) | def InAsmBlock(self):
method InTemplateArgumentList (line 2705) | def InTemplateArgumentList(self, clean_lines, linenum, pos):
method UpdatePreprocessor (line 2757) | def UpdatePreprocessor(self, line):
method Update (line 2814) | def Update(self, filename, clean_lines, linenum, error):
method InnermostClass (line 2978) | def InnermostClass(self):
method CheckCompletedBlocks (line 2990) | def CheckCompletedBlocks(self, filename, error):
function CheckForNonStandardConstructs (line 3012) | def CheckForNonStandardConstructs(filename, clean_lines, linenum,
function CheckSpacingForFunctionCall (line 3176) | def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
function IsBlankLine (line 3253) | def IsBlankLine(line):
function CheckForNamespaceIndentation (line 3268) | def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, l...
function CheckForFunctionLengths (line 3282) | def CheckForFunctionLengths(filename, clean_lines, linenum,
function CheckComment (line 3353) | def CheckComment(line, filename, linenum, next_line_start, error):
function CheckSpacing (line 3407) | def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
function CheckOperatorSpacing (line 3535) | def CheckOperatorSpacing(filename, clean_lines, linenum, error):
function CheckParenthesisSpacing (line 3650) | def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
function CheckCommaSpacing (line 3688) | def CheckCommaSpacing(filename, clean_lines, linenum, error):
function _IsType (line 3724) | def _IsType(clean_lines, nesting_state, expr):
function CheckBracesSpacing (line 3787) | def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, er...
function IsDecltype (line 3876) | def IsDecltype(clean_lines, linenum, column):
function CheckSectionSpacing (line 3893) | def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
function GetPreviousNonBlankLine (line 3948) | def GetPreviousNonBlankLine(clean_lines, linenum):
function CheckBraces (line 3971) | def CheckBraces(filename, clean_lines, linenum, error):
function CheckTrailingSemicolon (line 4090) | def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
function CheckEmptyBlockBody (line 4237) | def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
function FindCheckMacro (line 4341) | def FindCheckMacro(line):
function CheckCheck (line 4364) | def CheckCheck(filename, clean_lines, linenum, error):
function CheckAltTokens (line 4482) | def CheckAltTokens(filename, clean_lines, linenum, error):
function GetLineWidth (line 4514) | def GetLineWidth(line):
function CheckStyle (line 4546) | def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_s...
function _DropCommonSuffixes (line 4681) | def _DropCommonSuffixes(filename):
function _ClassifyInclude (line 4711) | def _ClassifyInclude(fileinfo, include, is_system):
function CheckIncludeLine (line 4777) | def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
function _GetTextInside (line 4868) | def _GetTextInside(text, start_pattern):
function CheckLanguage (line 4953) | def CheckLanguage(filename, clean_lines, linenum, file_extension,
function CheckGlobalStatic (line 5114) | def CheckGlobalStatic(filename, clean_lines, linenum, error):
function CheckPrintf (line 5175) | def CheckPrintf(filename, clean_lines, linenum, error):
function IsDerivedFunction (line 5204) | def IsDerivedFunction(clean_lines, linenum):
function IsOutOfLineMethodDefinition (line 5226) | def IsOutOfLineMethodDefinition(clean_lines, linenum):
function IsInitializerList (line 5242) | def IsInitializerList(clean_lines, linenum):
function CheckForNonConstReference (line 5284) | def CheckForNonConstReference(filename, clean_lines, linenum,
function CheckCasts (line 5423) | def CheckCasts(filename, clean_lines, linenum, error):
function CheckCStyleCast (line 5542) | def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, ...
function ExpectingFunctionArgs (line 5595) | def ExpectingFunctionArgs(clean_lines, linenum):
function FilesBelongToSameModule (line 5697) | def FilesBelongToSameModule(filename_cc, filename_h):
function UpdateIncludeState (line 5755) | def UpdateIncludeState(filename, include_dict, io=codecs):
function CheckForIncludeWhatYouUse (line 5782) | def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
function CheckMakePairUsesDeduction (line 5886) | def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
function CheckRedundantVirtual (line 5907) | def CheckRedundantVirtual(filename, clean_lines, linenum, error):
function CheckRedundantOverrideOrFinal (line 5971) | def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
function IsBlockInNameSpace (line 6004) | def IsBlockInNameSpace(nesting_state, is_forward_declaration):
function ShouldCheckNamespaceIndentation (line 6023) | def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_i...
function CheckItemIndentationInNamespace (line 6056) | def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, lin...
function ProcessLine (line 6064) | def ProcessLine(filename, file_extension, clean_lines, line,
function FlagCxx11Features (line 6109) | def FlagCxx11Features(filename, clean_lines, linenum, error):
function FlagCxx14Features (line 6161) | def FlagCxx14Features(filename, clean_lines, linenum, error):
function ProcessFileData (line 6180) | def ProcessFileData(filename, file_extension, lines, error,
function ProcessConfigOverrides (line 6231) | def ProcessConfigOverrides(filename):
function ProcessFile (line 6318) | def ProcessFile(filename, vlevel, extra_check_functions=None):
function PrintUsage (line 6410) | def PrintUsage(message):
function PrintVersion (line 6426) | def PrintVersion():
function PrintCategories (line 6432) | def PrintCategories():
function ParseArguments (line 6441) | def ParseArguments(args):
function _ExpandDirectories (line 6539) | def _ExpandDirectories(filenames):
function _FilterExcludedFiles (line 6571) | def _FilterExcludedFiles(filenames):
function main (line 6578) | def main():
FILE: code/day15/build_support/run_clang_format.py
function check (line 30) | def check(arguments, source_dir):
FILE: code/day15/build_support/run_clang_tidy.py
function find_compilation_database (line 60) | def find_compilation_database(path):
function make_absolute (line 71) | def make_absolute(f, directory):
function get_tidy_invocation (line 77) | def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path,
function merge_replacement_files (line 110) | def merge_replacement_files(tmpdir, mergefile):
function check_clang_apply_replacements_binary (line 134) | def check_clang_apply_replacements_binary(args):
function apply_fixes (line 145) | def apply_fixes(args, tmpdir):
function run_tidy (line 156) | def run_tidy(args, tmpdir, build_path, queue, lock, failed_files):
function main (line 193) | def main():
FILE: code/day15/build_support/run_clang_tidy_extra.py
class CheckConfig (line 17) | class CheckConfig(object):
method __init__ (line 20) | def __init__(self):
method _init_config (line 26) | def _init_config(self):
method should_skip (line 33) | def should_skip(self, path):
FILE: code/day15/src/Channel.cpp
function Socket (line 51) | Socket *Channel::GetSocket() { return socket_; }
FILE: code/day15/src/Connection.cpp
function Buffer (line 164) | Buffer *Connection::GetReadBuffer() { return read_buffer_; }
function Buffer (line 166) | Buffer *Connection::GetSendBuffer() { return send_buffer_; }
function Socket (line 185) | Socket *Connection::GetSocket() { return sock_; }
FILE: code/day15/src/Poller.cpp
type epoll_event (line 61) | struct epoll_event
type kevent (line 93) | struct kevent
type timespec (line 105) | struct timespec
type kevent (line 132) | struct kevent
type kevent (line 151) | struct kevent
FILE: code/day15/src/Socket.cpp
type sockaddr_in (line 36) | struct sockaddr_in
type sockaddr_in (line 49) | struct sockaddr_in
type sockaddr_in (line 73) | struct sockaddr_in
function sockaddr_in (line 123) | sockaddr_in InetAddress::GetAddr() { return addr_; }
FILE: code/day15/src/include/Acceptor.h
function class (line 19) | class Acceptor {
FILE: code/day15/src/include/Buffer.h
function class (line 15) | class Buffer {
FILE: code/day15/src/include/Channel.h
function class (line 18) | class Channel {
FILE: code/day15/src/include/Connection.h
type State (line 22) | enum State {
function Buffer (line 61) | Buffer *send_buffer_{nullptr};
FILE: code/day15/src/include/EventLoop.h
function class (line 18) | class EventLoop {
FILE: code/day15/src/include/Exception.h
type ExceptionType (line 16) | enum ExceptionType {
function class (line 21) | class Exception : public std::runtime_error {
function std (line 33) | static std::string ExceptionTypeToString(ExceptionType type) {
FILE: code/day15/src/include/Log.h
function class (line 12) | class Log
FILE: code/day15/src/include/Poller.h
type epoll_event (line 39) | struct epoll_event
type kevent (line 43) | struct kevent
FILE: code/day15/src/include/Server.h
function class (line 22) | class Server {
FILE: code/day15/src/include/SignalHandler.h
function signal_handler (line 17) | void signal_handler(int sig) {
type Signal (line 21) | struct Signal {
FILE: code/day15/src/include/Socket.h
function class (line 16) | class InetAddress {
function class (line 33) | class Socket {
FILE: code/day15/src/include/ThreadPool.h
function class (line 23) | class ThreadPool {
FILE: code/day15/src/util.cpp
function ErrorIf (line 16) | void ErrorIf(bool condition, const char *errmsg) {
FILE: code/day15/test/chat_client.cpp
function main (line 5) | int main() {
FILE: code/day15/test/chat_server.cpp
function main (line 8) | int main() {
FILE: code/day15/test/echo_client.cpp
function main (line 5) | int main() {
FILE: code/day15/test/echo_clients.cpp
function OneClient (line 11) | void OneClient(int msgs, int wait) {
function main (line 30) | int main(int argc, char *argv[]) {
FILE: code/day15/test/echo_server.cpp
function main (line 4) | int main() {
FILE: code/day15/test/http_server.cpp
function main (line 4) | int main() {
FILE: code/day16/build_support/cpplint.py
function unicode_escape_decode (line 673) | def unicode_escape_decode(x):
function ProcessHppHeadersOption (line 687) | def ProcessHppHeadersOption(val):
function IsHeaderExtension (line 694) | def IsHeaderExtension(file_extension):
function GetHeaderExtensions (line 697) | def GetHeaderExtensions():
function GetAllExtensions (line 706) | def GetAllExtensions():
function ProcessExtensionsOption (line 710) | def ProcessExtensionsOption(val):
function GetNonHeaderExtensions (line 720) | def GetNonHeaderExtensions():
function ParseNolintSuppressions (line 723) | def ParseNolintSuppressions(filename, raw_line, linenum, error):
function ProcessGlobalSuppresions (line 755) | def ProcessGlobalSuppresions(lines):
function ResetNolintSuppressions (line 773) | def ResetNolintSuppressions():
function IsErrorSuppressedByNolint (line 779) | def IsErrorSuppressedByNolint(category, linenum):
function Match (line 797) | def Match(pattern, s):
function ReplaceAll (line 807) | def ReplaceAll(pattern, rep, s):
function Search (line 825) | def Search(pattern, s):
function _IsSourceExtension (line 832) | def _IsSourceExtension(s):
class _IncludeState (line 837) | class _IncludeState(object):
method __init__ (line 872) | def __init__(self):
method FindHeader (line 878) | def FindHeader(self, header):
method ResetSection (line 893) | def ResetSection(self, directive):
method SetLastHeader (line 911) | def SetLastHeader(self, header_path):
method CanonicalizeAlphabeticalOrder (line 914) | def CanonicalizeAlphabeticalOrder(self, header_path):
method IsInAlphabeticalOrder (line 929) | def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
method CheckNextIncludeOrder (line 950) | def CheckNextIncludeOrder(self, header_type):
class _CppLintState (line 1004) | class _CppLintState(object):
method __init__ (line 1007) | def __init__(self):
method SetOutputFormat (line 1030) | def SetOutputFormat(self, output_format):
method SetQuiet (line 1034) | def SetQuiet(self, quiet):
method SetVerboseLevel (line 1040) | def SetVerboseLevel(self, level):
method SetCountingStyle (line 1046) | def SetCountingStyle(self, counting_style):
method SetFilters (line 1050) | def SetFilters(self, filters):
method AddFilters (line 1068) | def AddFilters(self, filters):
method BackupFilters (line 1079) | def BackupFilters(self):
method RestoreFilters (line 1083) | def RestoreFilters(self):
method ResetErrorCounts (line 1087) | def ResetErrorCounts(self):
method IncrementErrorCount (line 1092) | def IncrementErrorCount(self, category):
method PrintErrorCounts (line 1102) | def PrintErrorCounts(self):
method PrintInfo (line 1110) | def PrintInfo(self, message):
method PrintError (line 1114) | def PrintError(self, message):
method AddJUnitFailure (line 1120) | def AddJUnitFailure(self, filename, linenum, message, category, confid...
method FormatJUnitXML (line 1124) | def FormatJUnitXML(self):
function _OutputFormat (line 1171) | def _OutputFormat():
function _SetOutputFormat (line 1176) | def _SetOutputFormat(output_format):
function _Quiet (line 1180) | def _Quiet():
function _SetQuiet (line 1184) | def _SetQuiet(quiet):
function _VerboseLevel (line 1189) | def _VerboseLevel():
function _SetVerboseLevel (line 1194) | def _SetVerboseLevel(level):
function _SetCountingStyle (line 1199) | def _SetCountingStyle(level):
function _Filters (line 1204) | def _Filters():
function _SetFilters (line 1209) | def _SetFilters(filters):
function _AddFilters (line 1221) | def _AddFilters(filters):
function _BackupFilters (line 1233) | def _BackupFilters():
function _RestoreFilters (line 1237) | def _RestoreFilters():
class _FunctionState (line 1241) | class _FunctionState(object):
method __init__ (line 1247) | def __init__(self):
method Begin (line 1252) | def Begin(self, function_name):
method Count (line 1262) | def Count(self):
method Check (line 1267) | def Check(self, error, filename, linenum):
method End (line 1295) | def End(self):
class _IncludeError (line 1300) | class _IncludeError(Exception):
class FileInfo (line 1305) | class FileInfo(object):
method __init__ (line 1312) | def __init__(self, filename):
method FullName (line 1315) | def FullName(self):
method RepositoryName (line 1319) | def RepositoryName(self):
method Split (line 1379) | def Split(self):
method BaseName (line 1393) | def BaseName(self):
method Extension (line 1397) | def Extension(self):
method NoExtension (line 1401) | def NoExtension(self):
method IsSource (line 1405) | def IsSource(self):
function _ShouldPrintError (line 1410) | def _ShouldPrintError(category, confidence, linenum):
function Error (line 1438) | def Error(filename, linenum, category, confidence, message):
function IsCppString (line 1496) | def IsCppString(line):
function CleanseRawStrings (line 1513) | def CleanseRawStrings(raw_lines):
function FindNextMultiLineCommentStart (line 1589) | def FindNextMultiLineCommentStart(lines, lineix):
function FindNextMultiLineCommentEnd (line 1600) | def FindNextMultiLineCommentEnd(lines, lineix):
function RemoveMultiLineCommentsFromRange (line 1609) | def RemoveMultiLineCommentsFromRange(lines, begin, end):
function RemoveMultiLineComments (line 1617) | def RemoveMultiLineComments(filename, lines, error):
function CleanseComments (line 1633) | def CleanseComments(line):
class CleansedLines (line 1649) | class CleansedLines(object):
method __init__ (line 1660) | def __init__(self, lines):
method NumLines (line 1672) | def NumLines(self):
method _CollapseStrings (line 1677) | def _CollapseStrings(elided):
function FindEndOfExpressionInLine (line 1744) | def FindEndOfExpressionInLine(line, startpos, stack):
function CloseExpression (line 1822) | def CloseExpression(clean_lines, linenum, pos):
function FindStartOfExpressionInLine (line 1866) | def FindStartOfExpressionInLine(line, endpos, stack):
function ReverseCloseExpression (line 1943) | def ReverseCloseExpression(clean_lines, linenum, pos):
function CheckForCopyright (line 1981) | def CheckForCopyright(filename, lines, error):
function GetIndentLevel (line 1994) | def GetIndentLevel(line):
function PathSplitToList (line 2009) | def PathSplitToList(path):
function GetHeaderGuardCPPVariable (line 2034) | def GetHeaderGuardCPPVariable(filename):
function CheckForHeaderGuard (line 2110) | def CheckForHeaderGuard(filename, clean_lines, error):
function CheckHeaderFileIncluded (line 2213) | def CheckHeaderFileIncluded(filename, include_state, error):
function CheckForBadCharacters (line 2240) | def CheckForBadCharacters(filename, lines, error):
function CheckForNewlineAtEOF (line 2265) | def CheckForNewlineAtEOF(filename, lines, error):
function CheckForMultilineCommentsAndStrings (line 2283) | def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, ...
function CheckPosixThreading (line 2351) | def CheckPosixThreading(filename, clean_lines, linenum, error):
function CheckVlogArguments (line 2377) | def CheckVlogArguments(filename, clean_lines, linenum, error):
function CheckInvalidIncrement (line 2401) | def CheckInvalidIncrement(filename, clean_lines, linenum, error):
function IsMacroDefinition (line 2423) | def IsMacroDefinition(clean_lines, linenum):
function IsForwardClassDeclaration (line 2433) | def IsForwardClassDeclaration(clean_lines, linenum):
class _BlockInfo (line 2437) | class _BlockInfo(object):
method __init__ (line 2440) | def __init__(self, linenum, seen_open_brace):
method CheckBegin (line 2447) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2462) | def CheckEnd(self, filename, clean_lines, linenum, error):
method IsBlockInfo (line 2475) | def IsBlockInfo(self):
class _ExternCInfo (line 2487) | class _ExternCInfo(_BlockInfo):
method __init__ (line 2490) | def __init__(self, linenum):
class _ClassInfo (line 2494) | class _ClassInfo(_BlockInfo):
method __init__ (line 2497) | def __init__(self, name, class_or_struct, clean_lines, linenum):
method CheckBegin (line 2527) | def CheckBegin(self, filename, clean_lines, linenum, error):
method CheckEnd (line 2532) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _NamespaceInfo (line 2563) | class _NamespaceInfo(_BlockInfo):
method __init__ (line 2566) | def __init__(self, name, linenum):
method CheckEnd (line 2571) | def CheckEnd(self, filename, clean_lines, linenum, error):
class _PreprocessorInfo (line 2624) | class _PreprocessorInfo(object):
method __init__ (line 2627) | def __init__(self, stack_before_if):
class NestingState (line 2638) | class NestingState(object):
method __init__ (line 2641) | def __init__(self):
method SeenOpenBrace (line 2664) | def SeenOpenBrace(self):
method InNamespaceBody (line 2673) | def InNamespaceBody(self):
method InExternC (line 2681) | def InExternC(self):
method InClassDeclaration (line 2689) | def InClassDeclaration(self):
method InAsmBlock (line 2697) | def InAsmBlock(self):
method InTemplateArgumentList (line 2705) | def InTemplateArgumentList(self, clean_lines, linenum, pos):
method UpdatePreprocessor (line 2757) | def UpdatePreprocessor(self, line):
method Update (line 2814) | def Update(self, filename, clean_lines, linenum, error):
method InnermostClass (line 2978) | def InnermostClass(self):
method CheckCompletedBlocks (line 2990) | def CheckCompletedBlocks(self, filename, error):
function CheckForNonStandardConstructs (line 3012) | def CheckForNonStandardConstructs(filename, clean_lines, linenum,
function CheckSpacingForFunctionCall (line 3176) | def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
function IsBlankLine (line 3253) | def IsBlankLine(line):
function CheckForNamespaceIndentation (line 3268) | def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, l...
function CheckForFunctionLengths (line 3282) | def CheckForFunctionLengths(filename, clean_lines, linenum,
function CheckComment (line 3353) | def CheckComment(line, filename, linenum, next_line_start, error):
function CheckSpacing (line 3407) | def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
function CheckOperatorSpacing (line 3535) | def CheckOperatorSpacing(filename, clean_lines, linenum, error):
function CheckParenthesisSpacing (line 3650) | def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
function CheckCommaSpacing (line 3688) | def CheckCommaSpacing(filename, clean_lines, linenum, error):
function _IsType (line 3724) | def _IsType(clean_lines, nesting_state, expr):
function CheckBracesSpacing (line 3787) | def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, er...
function IsDecltype (line 3876) | def IsDecltype(clean_lines, linenum, column):
function CheckSectionSpacing (line 3893) | def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
function GetPreviousNonBlankLine (line 3948) | def GetPreviousNonBlankLine(clean_lines, linenum):
function CheckBraces (line 3971) | def CheckBraces(filename, clean_lines, linenum, error):
function CheckTrailingSemicolon (line 4090) | def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
function CheckEmptyBlockBody (line 4237) | def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
function FindCheckMacro (line 4341) | def FindCheckMacro(line):
function CheckCheck (line 4364) | def CheckCheck(filename, clean_lines, linenum, error):
function CheckAltTokens (line 4482) | def CheckAltTokens(filename, clean_lines, linenum, error):
function GetLineWidth (line 4514) | def GetLineWidth(line):
function CheckStyle (line 4546) | def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_s...
function _DropCommonSuffixes (line 4681) | def _DropCommonSuffixes(filename):
function _ClassifyInclude (line 4711) | def _ClassifyInclude(fileinfo, include, is_system):
function CheckIncludeLine (line 4777) | def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
function _GetTextInside (line 4868) | def _GetTextInside(text, start_pattern):
function CheckLanguage (line 4953) | def CheckLanguage(filename, clean_lines, linenum, file_extension,
function CheckGlobalStatic (line 5114) | def CheckGlobalStatic(filename, clean_lines, linenum, error):
function CheckPrintf (line 5175) | def CheckPrintf(filename, clean_lines, linenum, error):
function IsDerivedFunction (line 5204) | def IsDerivedFunction(clean_lines, linenum):
function IsOutOfLineMethodDefinition (line 5226) | def IsOutOfLineMethodDefinition(clean_lines, linenum):
function IsInitializerList (line 5242) | def IsInitializerList(clean_lines, linenum):
function CheckForNonConstReference (line 5284) | def CheckForNonConstReference(filename, clean_lines, linenum,
function CheckCasts (line 5423) | def CheckCasts(filename, clean_lines, linenum, error):
function CheckCStyleCast (line 5542) | def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, ...
function ExpectingFunctionArgs (line 5595) | def ExpectingFunctionArgs(clean_lines, linenum):
function FilesBelongToSameModule (line 5697) | def FilesBelongToSameModule(filename_cc, filename_h):
function UpdateIncludeState (line 5755) | def UpdateIncludeState(filename, include_dict, io=codecs):
function CheckForIncludeWhatYouUse (line 5782) | def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
function CheckMakePairUsesDeduction (line 5886) | def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
function CheckRedundantVirtual (line 5907) | def CheckRedundantVirtual(filename, clean_lines, linenum, error):
function CheckRedundantOverrideOrFinal (line 5971) | def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
function IsBlockInNameSpace (line 6004) | def IsBlockInNameSpace(nesting_state, is_forward_declaration):
function ShouldCheckNamespaceIndentation (line 6023) | def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_i...
function CheckItemIndentationInNamespace (line 6056) | def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, lin...
function ProcessLine (line 6064) | def ProcessLine(filename, file_extension, clean_lines, line,
function FlagCxx11Features (line 6109) | def FlagCxx11Features(filename, clean_lines, linenum, error):
function FlagCxx14Features (line 6161) | def FlagCxx14Features(filename, clean_lines, linenum, error):
function ProcessFileData (line 6180) | def ProcessFileData(filename, file_extension, lines, error,
function ProcessConfigOverrides (line 6231) | def ProcessConfigOverrides(filename):
function ProcessFile (line 6318) | def ProcessFile(filename, vlevel, extra_check_functions=None):
function PrintUsage (line 6410) | def PrintUsage(message):
function PrintVersion (line 6426) | def PrintVersion():
function PrintCategories (line 6432) | def PrintCategories():
function ParseArguments (line 6441) | def ParseArguments(args):
function _ExpandDirectories (line 6539) | def _ExpandDirectories(filenames):
function _FilterExcludedFiles (line 6571) | def _FilterExcludedFiles(filenames):
function main (line 6578) | def main():
FILE: code/day16/build_support/run_clang_format.py
function check (line 30) | def check(arguments, source_dir):
FILE: code/day16/build_support/run_clang_tidy.py
function find_compilation_database (line 60) | def find_compilation_database(path):
function make_absolute (line 71) | def make_absolute(f, directory):
function get_tidy_invocation (line 77) | def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path,
function merge_replacement_files (line 110) | def merge_replacement_files(tmpdir, mergefile):
function check_clang_apply_replacements_binary (line 134) | def check_clang_apply_replacements_binary(args):
function apply_fixes (line 145) | def apply_fixes(args, tmpdir):
function run_tidy (line 156) | def run_tidy(args, tmpdir, build_path, queue, lock, failed_files):
function main (line 193) | def main():
FILE: code/day16/build_support/run_clang_tidy_extra.py
class CheckConfig (line 17) | class CheckConfig(object):
method __init__ (line 20) | def __init__(self):
method _init_config (line 26) | def _init_config(self):
method should_skip (line 33) | def should_skip(self, path):
FILE: code/day16/src/Acceptor.cpp
function RC (line 33) | RC Acceptor::AcceptConnection() const{
FILE: code/day16/src/Connection.cpp
function RC (line 33) | RC Connection::Read() {
function RC (line 46) | RC Connection::Write() {
function RC (line 61) | RC Connection::ReadNonBlocking() {
function RC (line 89) | RC Connection::WriteNonBlocking() {
function RC (line 114) | RC Connection::ReadBlocking() {
function RC (line 134) | RC Connection::WriteBlocking() {
function RC (line 145) | RC Connection::Send(std::string msg) {
function Socket (line 168) | Socket *Connection::socket() const { return socket_.get(); }
function Buffer (line 171) | Buffer *Connection::read_buf() { return read_buf_.get(); }
function Buffer (line 172) | Buffer *Connection::send_buf() { return send_buf_.get(); }
FILE: code/day16/src/Poller.cpp
type epoll_event (line 60) | struct epoll_event
type kevent (line 92) | struct kevent
type timespec (line 105) | struct timespec
function RC (line 132) | RC Poller::UpdateChannel(Channel *ch) const {
function RC (line 155) | RC Poller::DeleteChannel(Channel *ch) const {
FILE: code/day16/src/Socket.cpp
type sockaddr_in (line 32) | struct sockaddr_in
type sockaddr (line 35) | struct sockaddr
function RC (line 44) | RC Socket::SetNonBlocking() const {
function RC (line 62) | RC Socket::Create() {
function RC (line 72) | RC Socket::Bind(const char *ip, uint16_t port) const {
function RC (line 86) | RC Socket::Listen() const {
function RC (line 95) | RC Socket::Accept(int &clnt_fd) const {
function RC (line 106) | RC Socket::Connect(const char *ip, uint16_t port) const {
FILE: code/day16/src/TcpServer.cpp
function RC (line 42) | RC TcpServer::NewConnection(int fd) {
function RC (line 59) | RC TcpServer::DeleteConnection(int fd) {
FILE: code/day16/src/include/Acceptor.h
function class (line 16) | class Acceptor {
FILE: code/day16/src/include/Buffer.h
function class (line 16) | class Buffer {
FILE: code/day16/src/include/Channel.h
function class (line 15) | class Channel {
FILE: code/day16/src/include/Connection.h
function class (line 15) | class Connection {
FILE: code/day16/src/include/EventLoop.h
function class (line 15) | class EventLoop {
FILE: code/day16/src/include/Exception.h
type ExceptionType (line 16) | enum ExceptionType {
function class (line 21) | class Exception : public std::runtime_error {
function std (line 33) | static std::string ExceptionTypeToString(ExceptionType type) {
FILE: code/day16/src/include/Log.h
function class (line 12) | class Log
FILE: code/day16/src/include/Poller.h
function class (line 23) | class Poller {
FILE: code/day16/src/include/SignalHandler.h
function signal_handler (line 17) | void signal_handler(int sig) {
type Signal (line 21) | struct Signal {
FILE: code/day16/src/include/Socket.h
function class (line 16) | class Socket {
FILE: code/day16/src/include/TcpServer.h
function class (line 17) | class TcpServer {
FILE: code/day16/src/include/ThreadPool.h
function class (line 23) | class ThreadPool {
FILE: code/day16/src/include/common.h
type RC (line 41) | enum RC {
FILE: code/day16/test/chat_client.cpp
function main (line 5) | int main() {
FILE: code/day16/test/chat_server.cpp
function main (line 8) | int main() {
FILE: code/day16/test/echo_client.cpp
function main (line 4) | int main() {
FILE: code/day16/test/echo_clients.cpp
function OneClient (line 5) | void OneClient(int msgs, int wait) {
function main (line 28) | int main(int argc, char *argv[]) {
FILE: code/day16/test/echo_server.cpp
function main (line 4) | int main() {
FILE: code/day16/test/http_server.cpp
function main (line 4) | int main() { return 0; }
Condensed preview — 370 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,553K chars).
[
{
"path": "README.md",
"chars": 2869,
"preview": "# 30天自制C++服务器\n\n> 该教程是本人学生时代初学C++的历程,工作后已无精力写完剩下部分,回顾当年的代码有诸多不完美甚至瑕疵,有意愿者可以自由修改、开发、续写该项目。\n\n先说结论:不管使用什么语言,一切后台开发的根基,是面向Lin"
},
{
"path": "code/day01/Makefile",
"chars": 61,
"preview": "server:\n\tg++ server.cpp -o server && g++ client.cpp -o client"
},
{
"path": "code/day01/client.cpp",
"chars": 794,
"preview": "/*\n * @Author: your name\n * @Date: 2022-01-04 20:03:45\n * @LastEditTime: 2022-01-05 19:08:58\n * @LastEditors: your name\n"
},
{
"path": "code/day01/server.cpp",
"chars": 797,
"preview": "#include <stdio.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n\nint main() {\n int sockfd = soc"
},
{
"path": "code/day02/Makefile",
"chars": 113,
"preview": "server:\n\tg++ util.cpp client.cpp -o client && \\\n\tg++ util.cpp server.cpp -o server\nclean:\n\trm server && rm client"
},
{
"path": "code/day02/client.cpp",
"chars": 1295,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"uti"
},
{
"path": "code/day02/server.cpp",
"chars": 1601,
"preview": "#include <stdio.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"util"
},
{
"path": "code/day02/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day02/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day03/Makefile",
"chars": 113,
"preview": "server:\n\tg++ util.cpp client.cpp -o client && \\\n\tg++ util.cpp server.cpp -o server\nclean:\n\trm server && rm client"
},
{
"path": "code/day03/client.cpp",
"chars": 1372,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"uti"
},
{
"path": "code/day03/server.cpp",
"chars": 3423,
"preview": "#include <stdio.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include <fcnt"
},
{
"path": "code/day03/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day03/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day04/Epoll.cpp",
"chars": 954,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 1000\n\nEpoll::Epoll() : "
},
{
"path": "code/day04/Epoll.h",
"chars": 254,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Epoll\n{\nprivate:\n int epfd;\n struct epoll_event *even"
},
{
"path": "code/day04/InetAddress.cpp",
"chars": 415,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day04/InetAddress.h",
"chars": 209,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\npublic:\n struct sockaddr_in addr;\n socklen_t addr_len;\n "
},
{
"path": "code/day04/Makefile",
"chars": 150,
"preview": "server:\n\tg++ util.cpp client.cpp -o client && \\\n\tg++ util.cpp server.cpp Epoll.cpp InetAddress.cpp Socket.cpp -o server\n"
},
{
"path": "code/day04/Socket.cpp",
"chars": 951,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day04/Socket.h",
"chars": 252,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int);\n ~Socket("
},
{
"path": "code/day04/client.cpp",
"chars": 1372,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"uti"
},
{
"path": "code/day04/server.cpp",
"chars": 2523,
"preview": "#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <vector>\n#incl"
},
{
"path": "code/day04/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day04/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day05/Channel.cpp",
"chars": 640,
"preview": "#include \"Channel.h\"\n#include \"Epoll.h\"\n\nChannel::Channel(Epoll *_ep, int _fd) : ep(_ep), fd(_fd), events(0), revents(0)"
},
{
"path": "code/day05/Channel.h",
"chars": 434,
"preview": "#pragma once\n#include <sys/epoll.h>\n\nclass Epoll;\nclass Channel\n{\nprivate:\n Epoll *ep;\n int fd;\n uint32_t event"
},
{
"path": "code/day05/Epoll.cpp",
"chars": 2026,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 10"
},
{
"path": "code/day05/Epoll.h",
"chars": 356,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Channel;\nclass Epoll\n{\nprivate:\n int epfd;\n struct ep"
},
{
"path": "code/day05/InetAddress.cpp",
"chars": 415,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day05/InetAddress.h",
"chars": 209,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\npublic:\n struct sockaddr_in addr;\n socklen_t addr_len;\n "
},
{
"path": "code/day05/Makefile",
"chars": 162,
"preview": "server:\n\tg++ util.cpp client.cpp -o client && \\\n\tg++ util.cpp server.cpp Epoll.cpp InetAddress.cpp Socket.cpp Channel.cp"
},
{
"path": "code/day05/Socket.cpp",
"chars": 951,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day05/Socket.h",
"chars": 252,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int);\n ~Socket("
},
{
"path": "code/day05/client.cpp",
"chars": 1372,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"uti"
},
{
"path": "code/day05/server.cpp",
"chars": 2719,
"preview": "#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <vector>\n#incl"
},
{
"path": "code/day05/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day05/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day06/Makefile",
"chars": 219,
"preview": "server:\n\tg++ src/util.cpp client.cpp -o client && \\\n\tg++ src/util.cpp server.cpp src/Epoll.cpp src/InetAddress.cpp src/S"
},
{
"path": "code/day06/client.cpp",
"chars": 1376,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"src"
},
{
"path": "code/day06/server.cpp",
"chars": 176,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day06/src/Channel.cpp",
"chars": 781,
"preview": "#include \"Channel.h\"\n#include \"EventLoop.h\"\n\nChannel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events("
},
{
"path": "code/day06/src/Channel.h",
"chars": 576,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <functional>\nclass EventLoop;\nclass Channel\n{\nprivate:\n EventLoop *loop;"
},
{
"path": "code/day06/src/Epoll.cpp",
"chars": 2026,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 10"
},
{
"path": "code/day06/src/Epoll.h",
"chars": 356,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Channel;\nclass Epoll\n{\nprivate:\n int epfd;\n struct ep"
},
{
"path": "code/day06/src/EventLoop.cpp",
"chars": 486,
"preview": "#include \"EventLoop.h\"\n#include \"Epoll.h\"\n#include \"Channel.h\"\n#include <vector>\n\nEventLoop::EventLoop() : ep(nullptr), "
},
{
"path": "code/day06/src/EventLoop.h",
"chars": 197,
"preview": "#pragma once\nclass Epoll;\nclass Channel;\nclass EventLoop\n{\nprivate:\n Epoll *ep;\n bool quit;\npublic:\n EventLoop("
},
{
"path": "code/day06/src/InetAddress.cpp",
"chars": 415,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day06/src/InetAddress.h",
"chars": 209,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\npublic:\n struct sockaddr_in addr;\n socklen_t addr_len;\n "
},
{
"path": "code/day06/src/Server.cpp",
"chars": 2196,
"preview": "#include \"Server.h\"\n#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"Channel.h\"\n#include <functional>\n#include <st"
},
{
"path": "code/day06/src/Server.h",
"chars": 216,
"preview": "#pragma once\n\nclass EventLoop;\nclass Socket;\nclass Server\n{\nprivate:\n EventLoop *loop;\npublic:\n Server(EventLoop*)"
},
{
"path": "code/day06/src/Socket.cpp",
"chars": 951,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day06/src/Socket.h",
"chars": 252,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int);\n ~Socket("
},
{
"path": "code/day06/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day06/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day07/Makefile",
"chars": 236,
"preview": "server:\n\tg++ src/util.cpp client.cpp -o client && \\\n\tg++ src/util.cpp server.cpp src/Epoll.cpp src/InetAddress.cpp src/S"
},
{
"path": "code/day07/client.cpp",
"chars": 1376,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"src"
},
{
"path": "code/day07/server.cpp",
"chars": 176,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day07/src/Acceptor.cpp",
"chars": 777,
"preview": "#include \"Acceptor.h\"\n#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"Channel.h\"\n#include \"Server.h\"\n\nAcceptor::A"
},
{
"path": "code/day07/src/Acceptor.h",
"chars": 428,
"preview": "#pragma once\n#include <functional>\n\nclass EventLoop;\nclass Socket;\nclass InetAddress;\nclass Channel;\nclass Acceptor\n{\npr"
},
{
"path": "code/day07/src/Channel.cpp",
"chars": 782,
"preview": "#include \"Channel.h\"\n#include \"EventLoop.h\"\n\nChannel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events("
},
{
"path": "code/day07/src/Channel.h",
"chars": 576,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <functional>\nclass EventLoop;\nclass Channel\n{\nprivate:\n EventLoop *loop;"
},
{
"path": "code/day07/src/Epoll.cpp",
"chars": 2026,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 10"
},
{
"path": "code/day07/src/Epoll.h",
"chars": 356,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Channel;\nclass Epoll\n{\nprivate:\n int epfd;\n struct ep"
},
{
"path": "code/day07/src/EventLoop.cpp",
"chars": 486,
"preview": "#include \"EventLoop.h\"\n#include \"Epoll.h\"\n#include \"Channel.h\"\n#include <vector>\n\nEventLoop::EventLoop() : ep(nullptr), "
},
{
"path": "code/day07/src/EventLoop.h",
"chars": 197,
"preview": "#pragma once\nclass Epoll;\nclass Channel;\nclass EventLoop\n{\nprivate:\n Epoll *ep;\n bool quit;\npublic:\n EventLoop("
},
{
"path": "code/day07/src/InetAddress.cpp",
"chars": 415,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day07/src/InetAddress.h",
"chars": 209,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\npublic:\n struct sockaddr_in addr;\n socklen_t addr_len;\n "
},
{
"path": "code/day07/src/Server.cpp",
"chars": 2010,
"preview": "#include \"Server.h\"\n#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"Channel.h\"\n#include \"Acceptor.h\"\n#include <fu"
},
{
"path": "code/day07/src/Server.h",
"chars": 256,
"preview": "#pragma once\n\nclass EventLoop;\nclass Socket;\nclass Acceptor;\nclass Server\n{\nprivate:\n EventLoop *loop;\n Acceptor *"
},
{
"path": "code/day07/src/Socket.cpp",
"chars": 951,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day07/src/Socket.h",
"chars": 252,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int);\n ~Socket("
},
{
"path": "code/day07/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day07/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day08/Makefile",
"chars": 264,
"preview": "server:\n\tg++ src/util.cpp client.cpp -o client && \\\n\tg++ server.cpp \\\n\tsrc/util.cpp src/Epoll.cpp src/InetAddress.cpp sr"
},
{
"path": "code/day08/client.cpp",
"chars": 1376,
"preview": "#include <iostream>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <unistd.h>\n#include \"src"
},
{
"path": "code/day08/server.cpp",
"chars": 177,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day08/src/Acceptor.cpp",
"chars": 1140,
"preview": "#include \"Acceptor.h\"\n#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"Channel.h\"\n\nAcceptor::Acceptor(EventLoop *_"
},
{
"path": "code/day08/src/Acceptor.h",
"chars": 386,
"preview": "#pragma once\n#include <functional>\n\nclass EventLoop;\nclass Socket;\nclass Channel;\nclass Acceptor\n{\nprivate:\n EventLoo"
},
{
"path": "code/day08/src/Channel.cpp",
"chars": 861,
"preview": "#include \"Channel.h\"\n#include \"EventLoop.h\"\n#include <unistd.h>\n\nChannel::Channel(EventLoop *_loop, int _fd) : loop(_loo"
},
{
"path": "code/day08/src/Channel.h",
"chars": 576,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <functional>\nclass EventLoop;\nclass Channel\n{\nprivate:\n EventLoop *loop;"
},
{
"path": "code/day08/src/Connection.cpp",
"chars": 1555,
"preview": "#include \"Connection.h\"\n#include \"Socket.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n#define READ_BU"
},
{
"path": "code/day08/src/Connection.h",
"chars": 410,
"preview": "#pragma once\n#include <functional>\n\nclass EventLoop;\nclass Socket;\nclass Channel;\nclass Connection\n{\nprivate:\n EventL"
},
{
"path": "code/day08/src/Epoll.cpp",
"chars": 2047,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 10"
},
{
"path": "code/day08/src/Epoll.h",
"chars": 359,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Channel;\nclass Epoll\n{\nprivate:\n int epfd;\n struct ep"
},
{
"path": "code/day08/src/EventLoop.cpp",
"chars": 486,
"preview": "#include \"EventLoop.h\"\n#include \"Epoll.h\"\n#include \"Channel.h\"\n#include <vector>\n\nEventLoop::EventLoop() : ep(nullptr), "
},
{
"path": "code/day08/src/EventLoop.h",
"chars": 198,
"preview": "#pragma once\n\nclass Epoll;\nclass Channel;\nclass EventLoop\n{\nprivate:\n Epoll *ep;\n bool quit;\npublic:\n EventLoop"
},
{
"path": "code/day08/src/InetAddress.cpp",
"chars": 649,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day08/src/InetAddress.h",
"chars": 336,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\nprivate:\n struct sockaddr_in addr;\n socklen_t addr_len;\np"
},
{
"path": "code/day08/src/Server.cpp",
"chars": 842,
"preview": "#include \"Server.h\"\n#include \"Socket.h\"\n#include \"Acceptor.h\"\n#include \"Connection.h\"\n#include <functional>\n\n\nServer::Se"
},
{
"path": "code/day08/src/Server.h",
"chars": 370,
"preview": "#pragma once\n\n#include <map>\nclass EventLoop;\nclass Socket;\nclass Acceptor;\nclass Connection;\nclass Server\n{\nprivate:\n "
},
{
"path": "code/day08/src/Socket.cpp",
"chars": 1224,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day08/src/Socket.h",
"chars": 256,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int _fd);\n ~Soc"
},
{
"path": "code/day08/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day08/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day09/Makefile",
"chars": 329,
"preview": "server:\n\tg++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client && \\\n\tg++ server.cpp \\\n"
},
{
"path": "code/day09/client.cpp",
"chars": 1436,
"preview": "#include <iostream>\n#include <unistd.h>\n#include <string.h>\n#include \"src/util.h\"\n#include \"src/Buffer.h\"\n#include \"src/"
},
{
"path": "code/day09/server.cpp",
"chars": 213,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day09/src/Acceptor.cpp",
"chars": 1140,
"preview": "#include \"Acceptor.h\"\n#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"Channel.h\"\n\nAcceptor::Acceptor(EventLoop *_"
},
{
"path": "code/day09/src/Acceptor.h",
"chars": 386,
"preview": "#pragma once\n#include <functional>\n\nclass EventLoop;\nclass Socket;\nclass Channel;\nclass Acceptor\n{\nprivate:\n EventLoo"
},
{
"path": "code/day09/src/Buffer.cpp",
"chars": 491,
"preview": "#include \"Buffer.h\"\n#include <string.h>\n#include <iostream>\nBuffer::Buffer()\n{\n}\n\nBuffer::~Buffer()\n{\n}\n\n\nvoid Buffer::a"
},
{
"path": "code/day09/src/Buffer.h",
"chars": 247,
"preview": "#pragma once\n#include <string>\n\nclass Buffer\n{\nprivate:\n std::string buf;\npublic:\n Buffer();\n ~Buffer();\n vo"
},
{
"path": "code/day09/src/Channel.cpp",
"chars": 861,
"preview": "#include \"Channel.h\"\n#include \"EventLoop.h\"\n#include <unistd.h>\n\nChannel::Channel(EventLoop *_loop, int _fd) : loop(_loo"
},
{
"path": "code/day09/src/Channel.h",
"chars": 576,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <functional>\nclass EventLoop;\nclass Channel\n{\nprivate:\n EventLoop *loop;"
},
{
"path": "code/day09/src/Connection.cpp",
"chars": 1817,
"preview": "#include \"Connection.h\"\n#include \"Socket.h\"\n#include \"Channel.h\"\n#include \"util.h\"\n#include \"Buffer.h\"\n#include <unistd."
},
{
"path": "code/day09/src/Connection.h",
"chars": 492,
"preview": "#pragma once\n#include <functional>\n#include <string>\nclass EventLoop;\nclass Socket;\nclass Channel;\nclass Buffer;\nclass C"
},
{
"path": "code/day09/src/Epoll.cpp",
"chars": 2047,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 10"
},
{
"path": "code/day09/src/Epoll.h",
"chars": 359,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Channel;\nclass Epoll\n{\nprivate:\n int epfd;\n struct ep"
},
{
"path": "code/day09/src/EventLoop.cpp",
"chars": 485,
"preview": "#include \"EventLoop.h\"\n#include \"Epoll.h\"\n#include \"Channel.h\"\n#include <vector>\n\nEventLoop::EventLoop() : ep(nullptr), "
},
{
"path": "code/day09/src/EventLoop.h",
"chars": 198,
"preview": "#pragma once\n\nclass Epoll;\nclass Channel;\nclass EventLoop\n{\nprivate:\n Epoll *ep;\n bool quit;\npublic:\n EventLoop"
},
{
"path": "code/day09/src/InetAddress.cpp",
"chars": 649,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day09/src/InetAddress.h",
"chars": 336,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\nprivate:\n struct sockaddr_in addr;\n socklen_t addr_len;\np"
},
{
"path": "code/day09/src/Server.cpp",
"chars": 841,
"preview": "#include \"Server.h\"\n#include \"Socket.h\"\n#include \"Acceptor.h\"\n#include \"Connection.h\"\n#include <functional>\n\n\nServer::Se"
},
{
"path": "code/day09/src/Server.h",
"chars": 370,
"preview": "#pragma once\n\n#include <map>\nclass EventLoop;\nclass Socket;\nclass Acceptor;\nclass Connection;\nclass Server\n{\nprivate:\n "
},
{
"path": "code/day09/src/Socket.cpp",
"chars": 1447,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day09/src/Socket.h",
"chars": 288,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int _fd);\n ~Soc"
},
{
"path": "code/day09/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day09/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day10/Makefile",
"chars": 446,
"preview": "server:\n\tg++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client && \\\n\tg++ server.cpp \\\n"
},
{
"path": "code/day10/ThreadPoolTest.cpp",
"chars": 497,
"preview": "#include <iostream>\n#include <string>\n#include \"src/ThreadPool.h\"\n\nvoid print(int a, double b, const char *c, std::strin"
},
{
"path": "code/day10/client.cpp",
"chars": 1436,
"preview": "#include <iostream>\n#include <unistd.h>\n#include <string.h>\n#include \"src/util.h\"\n#include \"src/Buffer.h\"\n#include \"src/"
},
{
"path": "code/day10/server.cpp",
"chars": 213,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day10/src/Acceptor.cpp",
"chars": 1140,
"preview": "#include \"Acceptor.h\"\n#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"Channel.h\"\n\nAcceptor::Acceptor(EventLoop *_"
},
{
"path": "code/day10/src/Acceptor.h",
"chars": 403,
"preview": "#pragma once\n#include <functional>\n#include <cstdio>\nclass EventLoop;\nclass Socket;\nclass Channel;\nclass Acceptor\n{\npriv"
},
{
"path": "code/day10/src/Buffer.cpp",
"chars": 491,
"preview": "#include \"Buffer.h\"\n#include <string.h>\n#include <iostream>\nBuffer::Buffer()\n{\n}\n\nBuffer::~Buffer()\n{\n}\n\n\nvoid Buffer::a"
},
{
"path": "code/day10/src/Buffer.h",
"chars": 247,
"preview": "#pragma once\n#include <string>\n\nclass Buffer\n{\nprivate:\n std::string buf;\npublic:\n Buffer();\n ~Buffer();\n vo"
},
{
"path": "code/day10/src/Channel.cpp",
"chars": 895,
"preview": "#include \"Channel.h\"\n#include \"EventLoop.h\"\n#include <unistd.h>\n\nChannel::Channel(EventLoop *_loop, int _fd) : loop(_loo"
},
{
"path": "code/day10/src/Channel.h",
"chars": 576,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <functional>\nclass EventLoop;\nclass Channel\n{\nprivate:\n EventLoop *loop;"
},
{
"path": "code/day10/src/Connection.cpp",
"chars": 1817,
"preview": "#include \"Connection.h\"\n#include \"Socket.h\"\n#include \"Channel.h\"\n#include \"util.h\"\n#include \"Buffer.h\"\n#include <unistd."
},
{
"path": "code/day10/src/Connection.h",
"chars": 492,
"preview": "#pragma once\n#include <functional>\n#include <string>\nclass EventLoop;\nclass Socket;\nclass Channel;\nclass Buffer;\nclass C"
},
{
"path": "code/day10/src/Epoll.cpp",
"chars": 2047,
"preview": "#include \"Epoll.h\"\n#include \"util.h\"\n#include \"Channel.h\"\n#include <unistd.h>\n#include <string.h>\n\n#define MAX_EVENTS 10"
},
{
"path": "code/day10/src/Epoll.h",
"chars": 359,
"preview": "#pragma once\n#include <sys/epoll.h>\n#include <vector>\n\nclass Channel;\nclass Epoll\n{\nprivate:\n int epfd;\n struct ep"
},
{
"path": "code/day10/src/EventLoop.cpp",
"chars": 650,
"preview": "#include \"EventLoop.h\"\n#include \"Epoll.h\"\n#include \"Channel.h\"\n#include \"ThreadPool.h\"\n#include <vector>\n\nEventLoop::Eve"
},
{
"path": "code/day10/src/EventLoop.h",
"chars": 310,
"preview": "#pragma once\n#include <functional>\n\nclass Epoll;\nclass Channel;\nclass ThreadPool;\nclass EventLoop\n{\nprivate:\n Epoll *"
},
{
"path": "code/day10/src/InetAddress.cpp",
"chars": 649,
"preview": "#include \"InetAddress.h\"\n#include <string.h>\nInetAddress::InetAddress() : addr_len(sizeof(addr)){\n bzero(&addr, sizeo"
},
{
"path": "code/day10/src/InetAddress.h",
"chars": 336,
"preview": "#pragma once\n#include <arpa/inet.h>\n\nclass InetAddress\n{\nprivate:\n struct sockaddr_in addr;\n socklen_t addr_len;\np"
},
{
"path": "code/day10/src/Server.cpp",
"chars": 841,
"preview": "#include \"Server.h\"\n#include \"Socket.h\"\n#include \"Acceptor.h\"\n#include \"Connection.h\"\n#include <functional>\n\n\nServer::Se"
},
{
"path": "code/day10/src/Server.h",
"chars": 370,
"preview": "#pragma once\n\n#include <map>\nclass EventLoop;\nclass Socket;\nclass Acceptor;\nclass Connection;\nclass Server\n{\nprivate:\n "
},
{
"path": "code/day10/src/Socket.cpp",
"chars": 1447,
"preview": "#include \"Socket.h\"\n#include \"InetAddress.h\"\n#include \"util.h\"\n#include <unistd.h>\n#include <fcntl.h>\n#include <sys/sock"
},
{
"path": "code/day10/src/Socket.h",
"chars": 288,
"preview": "#pragma once\n\nclass InetAddress;\nclass Socket\n{\nprivate:\n int fd;\npublic:\n Socket();\n Socket(int _fd);\n ~Soc"
},
{
"path": "code/day10/src/ThreadPool.cpp",
"chars": 1146,
"preview": "#include \"ThreadPool.h\"\n\nThreadPool::ThreadPool(int size) : stop(false){\n for(int i = 0; i < size; ++i){\n thre"
},
{
"path": "code/day10/src/ThreadPool.h",
"chars": 420,
"preview": "#pragma once\n#include <functional>\n#include <vector>\n#include <queue>\n#include <thread>\n#include <mutex>\n#include <condi"
},
{
"path": "code/day10/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day10/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day11/.vscode/launch.json",
"chars": 870,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n"
},
{
"path": "code/day11/Makefile",
"chars": 442,
"preview": "src=$(wildcard src/*.cpp)\n\nserver:\n\tg++ -std=c++11 -pthread -g \\\n\t$(src) \\\n\tserver.cpp \\\n\t-o server\n\t\nclient:\n\tg++ src/u"
},
{
"path": "code/day11/ThreadPoolTest.cpp",
"chars": 497,
"preview": "#include <iostream>\n#include <string>\n#include \"src/ThreadPool.h\"\n\nvoid print(int a, double b, const char *c, std::strin"
},
{
"path": "code/day11/client.cpp",
"chars": 1436,
"preview": "#include <iostream>\n#include <unistd.h>\n#include <string.h>\n#include \"src/util.h\"\n#include \"src/Buffer.h\"\n#include \"src/"
},
{
"path": "code/day11/server.cpp",
"chars": 177,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day11/src/Acceptor.cpp",
"chars": 1286,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Acceptor.h\"\n"
},
{
"path": "code/day11/src/Acceptor.h",
"chars": 484,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/Buffer.cpp",
"chars": 667,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Buffer.h\"\n#i"
},
{
"path": "code/day11/src/Buffer.h",
"chars": 380,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/Channel.cpp",
"chars": 1407,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Channel.h\"\n#"
},
{
"path": "code/day11/src/Channel.h",
"chars": 773,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/Connection.cpp",
"chars": 2529,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Connection.h"
},
{
"path": "code/day11/src/Connection.h",
"chars": 609,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/Epoll.cpp",
"chars": 1573,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Epoll.h\"\n#in"
},
{
"path": "code/day11/src/Epoll.h",
"chars": 396,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/EventLoop.cpp",
"chars": 771,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"EventLoop.h\""
},
{
"path": "code/day11/src/EventLoop.h",
"chars": 506,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n/*********************"
},
{
"path": "code/day11/src/InetAddress.cpp",
"chars": 568,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"InetAddress."
},
{
"path": "code/day11/src/InetAddress.h",
"chars": 363,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/Server.cpp",
"chars": 1198,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Server.h\"\n#i"
},
{
"path": "code/day11/src/Server.h",
"chars": 465,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/Socket.cpp",
"chars": 1410,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Socket.h\"\n#i"
},
{
"path": "code/day11/src/Socket.h",
"chars": 387,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n\n#pragma once\n\nclass I"
},
{
"path": "code/day11/src/ThreadPool.cpp",
"chars": 969,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"ThreadPool.h"
},
{
"path": "code/day11/src/ThreadPool.h",
"chars": 1432,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day11/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day11/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day11/test.cpp",
"chars": 2426,
"preview": "#include <iostream>\n#include <unistd.h>\n#include <string.h>\n#include <functional>\n#include \"src/util.h\"\n#include \"src/Bu"
},
{
"path": "code/day12/.vscode/launch.json",
"chars": 870,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n"
},
{
"path": "code/day12/Makefile",
"chars": 402,
"preview": "src=$(wildcard src/*.cpp)\n\nserver:\n\tg++ -std=c++11 -pthread -g \\\n\t$(src) \\\n\tserver.cpp \\\n\t-o server\n\t\nclient:\n\tg++ src/u"
},
{
"path": "code/day12/ThreadPoolTest.cpp",
"chars": 497,
"preview": "#include <iostream>\n#include <string>\n#include \"src/ThreadPool.h\"\n\nvoid print(int a, double b, const char *c, std::strin"
},
{
"path": "code/day12/client.cpp",
"chars": 1407,
"preview": "#include <iostream>\n#include <unistd.h>\n#include <string.h>\n#include \"src/util.h\"\n#include \"src/Buffer.h\"\n#include \"src/"
},
{
"path": "code/day12/server.cpp",
"chars": 177,
"preview": "#include \"src/EventLoop.h\"\n#include \"src/Server.h\"\n\nint main() {\n EventLoop *loop = new EventLoop();\n Server *serv"
},
{
"path": "code/day12/src/Acceptor.cpp",
"chars": 1216,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Acceptor.h\"\n"
},
{
"path": "code/day12/src/Acceptor.h",
"chars": 484,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/Buffer.cpp",
"chars": 667,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Buffer.h\"\n#i"
},
{
"path": "code/day12/src/Buffer.h",
"chars": 380,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/Channel.cpp",
"chars": 1131,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Channel.h\"\n#"
},
{
"path": "code/day12/src/Channel.h",
"chars": 705,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/Connection.cpp",
"chars": 2434,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Connection.h"
},
{
"path": "code/day12/src/Connection.h",
"chars": 564,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/Epoll.cpp",
"chars": 1573,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Epoll.h\"\n#in"
},
{
"path": "code/day12/src/Epoll.h",
"chars": 396,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/EventLoop.cpp",
"chars": 585,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"EventLoop.h\""
},
{
"path": "code/day12/src/EventLoop.h",
"chars": 460,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n/*********************"
},
{
"path": "code/day12/src/Server.cpp",
"chars": 1686,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"Server.h\"\n#i"
},
{
"path": "code/day12/src/Server.h",
"chars": 573,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/Socket.cpp",
"chars": 3746,
"preview": "/******************************\n* author: yuesong-feng\n* 客户端、服务器共用\n* accept,connect都支持非阻塞式IO,但只是简单处理,如果情况太复杂可能会有意料"
},
{
"path": "code/day12/src/Socket.h",
"chars": 662,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n\n#pragma once\n#include"
},
{
"path": "code/day12/src/ThreadPool.cpp",
"chars": 969,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#include \"ThreadPool.h"
},
{
"path": "code/day12/src/ThreadPool.h",
"chars": 1467,
"preview": "/******************************\n* author: yuesong-feng\n* \n*\n*\n******************************/\n#pragma once\n#include "
},
{
"path": "code/day12/src/util.cpp",
"chars": 184,
"preview": "#include \"util.h\"\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid errif(bool condition, const char *errmsg){\n if(conditi"
},
{
"path": "code/day12/src/util.h",
"chars": 69,
"preview": "#ifndef UTIL_H\n#define UTIL_H\n\nvoid errif(bool, const char*);\n\n#endif"
},
{
"path": "code/day12/test.cpp",
"chars": 2452,
"preview": "#include <iostream>\n#include <unistd.h>\n#include <string.h>\n#include <functional>\n#include \"src/util.h\"\n#include \"src/Bu"
},
{
"path": "code/day13/.clang-format",
"chars": 228,
"preview": "BasedOnStyle: Google\nDerivePointerAlignment: false\nPointerAlignment: Right\nColumnLimit: 120\n\n# Default for clang-8, chan"
},
{
"path": "code/day13/.clang-tidy",
"chars": 2264,
"preview": "---\nChecks: '\n bugprone-*,\n -bugprone-exception-escape,\n\n clang-analyzer-*,\n\n "
}
]
// ... and 170 more files (download for full content)
About this extraction
This page contains the full source code of the yuesong-feng/30dayMakeCppServer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 370 files (1.4 MB), approximately 392.1k tokens, and a symbol index with 1090 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.