├── .DS_Store ├── 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 /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuesong-feng/30dayMakeCppServer/5e3386d6d89b5d8c8898cf5283a6c92a43e373a9/.DS_Store -------------------------------------------------------------------------------- /code/day01/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ server.cpp -o server && g++ client.cpp -o client -------------------------------------------------------------------------------- /code/day01/client.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: your name 3 | * @Date: 2022-01-04 20:03:45 4 | * @LastEditTime: 2022-01-05 19:08:58 5 | * @LastEditors: your name 6 | * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE 7 | * @FilePath: \30dayMakeCppServer\code\day01\client.cpp 8 | */ 9 | #include 10 | #include 11 | #include 12 | 13 | int main() { 14 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 15 | 16 | struct sockaddr_in serv_addr; 17 | bzero(&serv_addr, sizeof(serv_addr)); 18 | serv_addr.sin_family = AF_INET; 19 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 20 | serv_addr.sin_port = htons(8888); 21 | 22 | //bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)); 客户端不进行bind操作 23 | 24 | connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /code/day01/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 8 | 9 | struct sockaddr_in serv_addr; 10 | bzero(&serv_addr, sizeof(serv_addr)); 11 | serv_addr.sin_family = AF_INET; 12 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 13 | serv_addr.sin_port = htons(8888); 14 | 15 | bind(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)); 16 | 17 | listen(sockfd, SOMAXCONN); 18 | 19 | struct sockaddr_in clnt_addr; 20 | socklen_t clnt_addr_len = sizeof(clnt_addr); 21 | bzero(&clnt_addr, sizeof(clnt_addr)); 22 | 23 | int clnt_sockfd = accept(sockfd, (sockaddr*)&clnt_addr, &clnt_addr_len); 24 | 25 | printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port)); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /code/day02/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ util.cpp client.cpp -o client && \ 3 | g++ util.cpp server.cpp -o server 4 | clean: 5 | rm server && rm client -------------------------------------------------------------------------------- /code/day02/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "util.h" 7 | 8 | 9 | int main() { 10 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 11 | errif(sockfd == -1, "socket create error"); 12 | 13 | struct sockaddr_in serv_addr; 14 | bzero(&serv_addr, sizeof(serv_addr)); 15 | serv_addr.sin_family = AF_INET; 16 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 17 | serv_addr.sin_port = htons(8888); 18 | 19 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 20 | 21 | while(true){ 22 | char buf[1024]; 23 | bzero(&buf, sizeof(buf)); 24 | scanf("%s", buf); 25 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 26 | if(write_bytes == -1){ 27 | printf("socket already disconnected, can't write any more!\n"); 28 | break; 29 | } 30 | bzero(&buf, sizeof(buf)); 31 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 32 | if(read_bytes > 0){ 33 | printf("message from server: %s\n", buf); 34 | }else if(read_bytes == 0){ 35 | printf("server socket disconnected!\n"); 36 | break; 37 | }else if(read_bytes == -1){ 38 | close(sockfd); 39 | errif(true, "socket read error"); 40 | } 41 | } 42 | close(sockfd); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /code/day02/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day02/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day03/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ util.cpp client.cpp -o client && \ 3 | g++ util.cpp server.cpp -o server 4 | clean: 5 | rm server && rm client -------------------------------------------------------------------------------- /code/day03/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "util.h" 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main() { 11 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 12 | errif(sockfd == -1, "socket create error"); 13 | 14 | struct sockaddr_in serv_addr; 15 | bzero(&serv_addr, sizeof(serv_addr)); 16 | serv_addr.sin_family = AF_INET; 17 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | serv_addr.sin_port = htons(8888); 19 | 20 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 21 | 22 | while(true){ 23 | char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么? 24 | bzero(&buf, sizeof(buf)); 25 | scanf("%s", buf); 26 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 27 | if(write_bytes == -1){ 28 | printf("socket already disconnected, can't write any more!\n"); 29 | break; 30 | } 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | printf("message from server: %s\n", buf); 35 | }else if(read_bytes == 0){ 36 | printf("server socket disconnected!\n"); 37 | break; 38 | }else if(read_bytes == -1){ 39 | close(sockfd); 40 | errif(true, "socket read error"); 41 | } 42 | } 43 | close(sockfd); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/day03/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day03/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day04/Epoll.cpp: -------------------------------------------------------------------------------- 1 | #include "Epoll.h" 2 | #include "util.h" 3 | #include 4 | #include 5 | 6 | #define MAX_EVENTS 1000 7 | 8 | Epoll::Epoll() : epfd(-1), events(nullptr){ 9 | epfd = epoll_create1(0); 10 | errif(epfd == -1, "epoll create error"); 11 | events = new epoll_event[MAX_EVENTS]; 12 | bzero(events, sizeof(*events) * MAX_EVENTS); 13 | } 14 | 15 | Epoll::~Epoll(){ 16 | if(epfd != -1){ 17 | close(epfd); 18 | epfd = -1; 19 | } 20 | delete [] events; 21 | } 22 | 23 | void Epoll::addFd(int fd, uint32_t op){ 24 | struct epoll_event ev; 25 | bzero(&ev, sizeof(ev)); 26 | ev.data.fd = fd; 27 | ev.events = op; 28 | errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add event error"); 29 | } 30 | 31 | std::vector Epoll::poll(int timeout){ 32 | std::vector activeEvents; 33 | int nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout); 34 | errif(nfds == -1, "epoll wait error"); 35 | for(int i = 0; i < nfds; ++i){ 36 | activeEvents.push_back(events[i]); 37 | } 38 | return activeEvents; 39 | } -------------------------------------------------------------------------------- /code/day04/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Epoll 6 | { 7 | private: 8 | int epfd; 9 | struct epoll_event *events; 10 | public: 11 | Epoll(); 12 | ~Epoll(); 13 | 14 | void addFd(int fd, uint32_t op); 15 | std::vector poll(int timeout = -1); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day04/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | -------------------------------------------------------------------------------- /code/day04/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | public: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | InetAddress(); 10 | InetAddress(const char* ip, uint16_t port); 11 | ~InetAddress(); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /code/day04/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ util.cpp client.cpp -o client && \ 3 | g++ util.cpp server.cpp Epoll.cpp InetAddress.cpp Socket.cpp -o server 4 | clean: 5 | rm server && rm client -------------------------------------------------------------------------------- /code/day04/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | 8 | Socket::Socket() : fd(-1){ 9 | fd = socket(AF_INET, SOCK_STREAM, 0); 10 | errif(fd == -1, "socket create error"); 11 | } 12 | Socket::Socket(int _fd) : fd(_fd){ 13 | errif(fd == -1, "socket create error"); 14 | } 15 | 16 | Socket::~Socket(){ 17 | if(fd != -1){ 18 | close(fd); 19 | fd = -1; 20 | } 21 | } 22 | 23 | void Socket::bind(InetAddress *addr){ 24 | errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error"); 25 | } 26 | 27 | void Socket::listen(){ 28 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 29 | } 30 | void Socket::setnonblocking(){ 31 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 32 | } 33 | 34 | int Socket::accept(InetAddress *addr){ 35 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len); 36 | errif(clnt_sockfd == -1, "socket accept error"); 37 | return clnt_sockfd; 38 | } 39 | 40 | int Socket::getFd(){ 41 | return fd; 42 | } -------------------------------------------------------------------------------- /code/day04/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | 19 | int getFd(); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /code/day04/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "util.h" 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main() { 11 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 12 | errif(sockfd == -1, "socket create error"); 13 | 14 | struct sockaddr_in serv_addr; 15 | bzero(&serv_addr, sizeof(serv_addr)); 16 | serv_addr.sin_family = AF_INET; 17 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | serv_addr.sin_port = htons(8888); 19 | 20 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 21 | 22 | while(true){ 23 | char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么? 24 | bzero(&buf, sizeof(buf)); 25 | scanf("%s", buf); 26 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 27 | if(write_bytes == -1){ 28 | printf("socket already disconnected, can't write any more!\n"); 29 | break; 30 | } 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | printf("message from server: %s\n", buf); 35 | }else if(read_bytes == 0){ 36 | printf("server socket disconnected!\n"); 37 | break; 38 | }else if(read_bytes == -1){ 39 | close(sockfd); 40 | errif(true, "socket read error"); 41 | } 42 | } 43 | close(sockfd); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/day04/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day04/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day05/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "Epoll.h" 3 | 4 | Channel::Channel(Epoll *_ep, int _fd) : ep(_ep), fd(_fd), events(0), revents(0), inEpoll(false){ 5 | 6 | } 7 | 8 | Channel::~Channel() 9 | { 10 | } 11 | 12 | void Channel::enableReading(){ 13 | events = EPOLLIN | EPOLLET; 14 | ep->updateChannel(this); 15 | } 16 | 17 | int Channel::getFd(){ 18 | return fd; 19 | } 20 | 21 | uint32_t Channel::getEvents(){ 22 | return events; 23 | } 24 | uint32_t Channel::getRevents(){ 25 | return revents; 26 | } 27 | 28 | bool Channel::getInEpoll(){ 29 | return inEpoll; 30 | } 31 | 32 | void Channel::setInEpoll(){ 33 | inEpoll = true; 34 | } 35 | 36 | // void Channel::setEvents(uint32_t _ev){ 37 | // events = _ev; 38 | // } 39 | 40 | void Channel::setRevents(uint32_t _ev){ 41 | revents = _ev; 42 | } -------------------------------------------------------------------------------- /code/day05/Channel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Epoll; 5 | class Channel 6 | { 7 | private: 8 | Epoll *ep; 9 | int fd; 10 | uint32_t events; 11 | uint32_t revents; 12 | bool inEpoll; 13 | public: 14 | Channel(Epoll *_ep, int _fd); 15 | ~Channel(); 16 | 17 | void enableReading(); 18 | 19 | int getFd(); 20 | uint32_t getEvents(); 21 | uint32_t getRevents(); 22 | bool getInEpoll(); 23 | void setInEpoll(); 24 | 25 | // void setEvents(uint32_t); 26 | void setRevents(uint32_t); 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /code/day05/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Channel; 6 | class Epoll 7 | { 8 | private: 9 | int epfd; 10 | struct epoll_event *events; 11 | public: 12 | Epoll(); 13 | ~Epoll(); 14 | 15 | void addFd(int fd, uint32_t op); 16 | void updateChannel(Channel*); 17 | // std::vector poll(int timeout = -1); 18 | std::vector poll(int timeout = -1); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day05/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | -------------------------------------------------------------------------------- /code/day05/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | public: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | InetAddress(); 10 | InetAddress(const char* ip, uint16_t port); 11 | ~InetAddress(); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /code/day05/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ util.cpp client.cpp -o client && \ 3 | g++ util.cpp server.cpp Epoll.cpp InetAddress.cpp Socket.cpp Channel.cpp -o server 4 | clean: 5 | rm server && rm client -------------------------------------------------------------------------------- /code/day05/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | 8 | Socket::Socket() : fd(-1){ 9 | fd = socket(AF_INET, SOCK_STREAM, 0); 10 | errif(fd == -1, "socket create error"); 11 | } 12 | Socket::Socket(int _fd) : fd(_fd){ 13 | errif(fd == -1, "socket create error"); 14 | } 15 | 16 | Socket::~Socket(){ 17 | if(fd != -1){ 18 | close(fd); 19 | fd = -1; 20 | } 21 | } 22 | 23 | void Socket::bind(InetAddress *addr){ 24 | errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error"); 25 | } 26 | 27 | void Socket::listen(){ 28 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 29 | } 30 | void Socket::setnonblocking(){ 31 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 32 | } 33 | 34 | int Socket::accept(InetAddress *addr){ 35 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len); 36 | errif(clnt_sockfd == -1, "socket accept error"); 37 | return clnt_sockfd; 38 | } 39 | 40 | int Socket::getFd(){ 41 | return fd; 42 | } -------------------------------------------------------------------------------- /code/day05/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | 19 | int getFd(); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /code/day05/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "util.h" 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main() { 11 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 12 | errif(sockfd == -1, "socket create error"); 13 | 14 | struct sockaddr_in serv_addr; 15 | bzero(&serv_addr, sizeof(serv_addr)); 16 | serv_addr.sin_family = AF_INET; 17 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | serv_addr.sin_port = htons(8888); 19 | 20 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 21 | 22 | while(true){ 23 | char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么? 24 | bzero(&buf, sizeof(buf)); 25 | scanf("%s", buf); 26 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 27 | if(write_bytes == -1){ 28 | printf("socket already disconnected, can't write any more!\n"); 29 | break; 30 | } 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | printf("message from server: %s\n", buf); 35 | }else if(read_bytes == 0){ 36 | printf("server socket disconnected!\n"); 37 | break; 38 | }else if(read_bytes == -1){ 39 | close(sockfd); 40 | errif(true, "socket read error"); 41 | } 42 | } 43 | close(sockfd); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/day05/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day05/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day06/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ src/util.cpp client.cpp -o client && \ 3 | 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 4 | clean: 5 | rm server && rm client -------------------------------------------------------------------------------- /code/day06/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "src/util.h" 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main() { 11 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 12 | errif(sockfd == -1, "socket create error"); 13 | 14 | struct sockaddr_in serv_addr; 15 | bzero(&serv_addr, sizeof(serv_addr)); 16 | serv_addr.sin_family = AF_INET; 17 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | serv_addr.sin_port = htons(8888); 19 | 20 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 21 | 22 | while(true){ 23 | char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么? 24 | bzero(&buf, sizeof(buf)); 25 | scanf("%s", buf); 26 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 27 | if(write_bytes == -1){ 28 | printf("socket already disconnected, can't write any more!\n"); 29 | break; 30 | } 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | printf("message from server: %s\n", buf); 35 | }else if(read_bytes == 0){ 36 | printf("server socket disconnected!\n"); 37 | break; 38 | }else if(read_bytes == -1){ 39 | close(sockfd); 40 | errif(true, "socket read error"); 41 | } 42 | } 43 | close(sockfd); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/day06/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /code/day06/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){ 5 | 6 | } 7 | 8 | Channel::~Channel() 9 | { 10 | } 11 | 12 | void Channel::handleEvent(){ 13 | callback(); 14 | } 15 | 16 | void Channel::enableReading(){ 17 | events = EPOLLIN | EPOLLET; 18 | loop->updateChannel(this); 19 | } 20 | 21 | int Channel::getFd(){ 22 | return fd; 23 | } 24 | 25 | uint32_t Channel::getEvents(){ 26 | return events; 27 | } 28 | uint32_t Channel::getRevents(){ 29 | return revents; 30 | } 31 | 32 | bool Channel::getInEpoll(){ 33 | return inEpoll; 34 | } 35 | 36 | void Channel::setInEpoll(){ 37 | inEpoll = true; 38 | } 39 | 40 | // void Channel::setEvents(uint32_t _ev){ 41 | // events = _ev; 42 | // } 43 | 44 | void Channel::setRevents(uint32_t _ev){ 45 | revents = _ev; 46 | } 47 | 48 | void Channel::setCallback(std::function _cb){ 49 | callback = _cb; 50 | } -------------------------------------------------------------------------------- /code/day06/src/Channel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Channel 6 | { 7 | private: 8 | EventLoop *loop; 9 | int fd; 10 | uint32_t events; 11 | uint32_t revents; 12 | bool inEpoll; 13 | std::function callback; 14 | public: 15 | Channel(EventLoop *_loop, int _fd); 16 | ~Channel(); 17 | 18 | void handleEvent(); 19 | void enableReading(); 20 | 21 | int getFd(); 22 | uint32_t getEvents(); 23 | uint32_t getRevents(); 24 | bool getInEpoll(); 25 | void setInEpoll(); 26 | 27 | // void setEvents(uint32_t); 28 | void setRevents(uint32_t); 29 | void setCallback(std::function); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /code/day06/src/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Channel; 6 | class Epoll 7 | { 8 | private: 9 | int epfd; 10 | struct epoll_event *events; 11 | public: 12 | Epoll(); 13 | ~Epoll(); 14 | 15 | void addFd(int fd, uint32_t op); 16 | void updateChannel(Channel*); 17 | // std::vector poll(int timeout = -1); 18 | std::vector poll(int timeout = -1); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day06/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "Epoll.h" 3 | #include "Channel.h" 4 | #include 5 | 6 | EventLoop::EventLoop() : ep(nullptr), quit(false){ 7 | ep = new Epoll(); 8 | } 9 | 10 | EventLoop::~EventLoop() 11 | { 12 | delete ep; 13 | } 14 | 15 | 16 | void EventLoop::loop(){ 17 | while(!quit){ 18 | std::vector chs; 19 | chs = ep->poll(); 20 | for(auto it = chs.begin(); it != chs.end(); ++it){ 21 | (*it)->handleEvent(); 22 | } 23 | } 24 | } 25 | 26 | void EventLoop::updateChannel(Channel *ch){ 27 | ep->updateChannel(ch); 28 | } -------------------------------------------------------------------------------- /code/day06/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class Epoll; 3 | class Channel; 4 | class EventLoop 5 | { 6 | private: 7 | Epoll *ep; 8 | bool quit; 9 | public: 10 | EventLoop(); 11 | ~EventLoop(); 12 | 13 | void loop(); 14 | void updateChannel(Channel*); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /code/day06/src/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | -------------------------------------------------------------------------------- /code/day06/src/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | public: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | InetAddress(); 10 | InetAddress(const char* ip, uint16_t port); 11 | ~InetAddress(); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /code/day06/src/Server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class EventLoop; 4 | class Socket; 5 | class Server 6 | { 7 | private: 8 | EventLoop *loop; 9 | public: 10 | Server(EventLoop*); 11 | ~Server(); 12 | 13 | void handleReadEvent(int); 14 | void newConnection(Socket *serv_sock); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /code/day06/src/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | 8 | Socket::Socket() : fd(-1){ 9 | fd = socket(AF_INET, SOCK_STREAM, 0); 10 | errif(fd == -1, "socket create error"); 11 | } 12 | Socket::Socket(int _fd) : fd(_fd){ 13 | errif(fd == -1, "socket create error"); 14 | } 15 | 16 | Socket::~Socket(){ 17 | if(fd != -1){ 18 | close(fd); 19 | fd = -1; 20 | } 21 | } 22 | 23 | void Socket::bind(InetAddress *addr){ 24 | errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error"); 25 | } 26 | 27 | void Socket::listen(){ 28 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 29 | } 30 | void Socket::setnonblocking(){ 31 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 32 | } 33 | 34 | int Socket::accept(InetAddress *addr){ 35 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len); 36 | errif(clnt_sockfd == -1, "socket accept error"); 37 | return clnt_sockfd; 38 | } 39 | 40 | int Socket::getFd(){ 41 | return fd; 42 | } -------------------------------------------------------------------------------- /code/day06/src/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | 19 | int getFd(); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /code/day06/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day06/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day07/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ src/util.cpp client.cpp -o client && \ 3 | 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 4 | clean: 5 | rm server && rm client -------------------------------------------------------------------------------- /code/day07/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "src/util.h" 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main() { 11 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 12 | errif(sockfd == -1, "socket create error"); 13 | 14 | struct sockaddr_in serv_addr; 15 | bzero(&serv_addr, sizeof(serv_addr)); 16 | serv_addr.sin_family = AF_INET; 17 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | serv_addr.sin_port = htons(8888); 19 | 20 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 21 | 22 | while(true){ 23 | char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么? 24 | bzero(&buf, sizeof(buf)); 25 | scanf("%s", buf); 26 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 27 | if(write_bytes == -1){ 28 | printf("socket already disconnected, can't write any more!\n"); 29 | break; 30 | } 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | printf("message from server: %s\n", buf); 35 | }else if(read_bytes == 0){ 36 | printf("server socket disconnected!\n"); 37 | break; 38 | }else if(read_bytes == -1){ 39 | close(sockfd); 40 | errif(true, "socket read error"); 41 | } 42 | } 43 | close(sockfd); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/day07/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /code/day07/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "Socket.h" 3 | #include "InetAddress.h" 4 | #include "Channel.h" 5 | #include "Server.h" 6 | 7 | Acceptor::Acceptor(EventLoop *_loop) : loop(_loop) 8 | { 9 | sock = new Socket(); 10 | addr = new InetAddress("127.0.0.1", 8888); 11 | sock->bind(addr); 12 | sock->listen(); 13 | sock->setnonblocking(); 14 | acceptChannel = new Channel(loop, sock->getFd()); 15 | std::function cb = std::bind(&Acceptor::acceptConnection, this); 16 | acceptChannel->setCallback(cb); 17 | acceptChannel->enableReading(); 18 | } 19 | 20 | Acceptor::~Acceptor(){ 21 | delete sock; 22 | delete addr; 23 | delete acceptChannel; 24 | } 25 | 26 | void Acceptor::acceptConnection(){ 27 | newConnectionCallback(sock); 28 | } 29 | 30 | void Acceptor::setNewConnectionCallback(std::function _cb){ 31 | newConnectionCallback = _cb; 32 | } -------------------------------------------------------------------------------- /code/day07/src/Acceptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class EventLoop; 5 | class Socket; 6 | class InetAddress; 7 | class Channel; 8 | class Acceptor 9 | { 10 | private: 11 | EventLoop *loop; 12 | Socket *sock; 13 | InetAddress *addr; 14 | Channel *acceptChannel; 15 | public: 16 | Acceptor(EventLoop *_loop); 17 | ~Acceptor(); 18 | void acceptConnection(); 19 | std::function newConnectionCallback; 20 | void setNewConnectionCallback(std::function); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /code/day07/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | 4 | Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){ 5 | 6 | } 7 | 8 | Channel::~Channel() 9 | { 10 | } 11 | 12 | void Channel::handleEvent(){ 13 | callback(); 14 | } 15 | 16 | void Channel::enableReading(){ 17 | events |= EPOLLIN | EPOLLET; 18 | loop->updateChannel(this); 19 | } 20 | 21 | int Channel::getFd(){ 22 | return fd; 23 | } 24 | 25 | uint32_t Channel::getEvents(){ 26 | return events; 27 | } 28 | uint32_t Channel::getRevents(){ 29 | return revents; 30 | } 31 | 32 | bool Channel::getInEpoll(){ 33 | return inEpoll; 34 | } 35 | 36 | void Channel::setInEpoll(){ 37 | inEpoll = true; 38 | } 39 | 40 | // void Channel::setEvents(uint32_t _ev){ 41 | // events = _ev; 42 | // } 43 | 44 | void Channel::setRevents(uint32_t _ev){ 45 | revents = _ev; 46 | } 47 | 48 | void Channel::setCallback(std::function _cb){ 49 | callback = _cb; 50 | } -------------------------------------------------------------------------------- /code/day07/src/Channel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Channel 6 | { 7 | private: 8 | EventLoop *loop; 9 | int fd; 10 | uint32_t events; 11 | uint32_t revents; 12 | bool inEpoll; 13 | std::function callback; 14 | public: 15 | Channel(EventLoop *_loop, int _fd); 16 | ~Channel(); 17 | 18 | void handleEvent(); 19 | void enableReading(); 20 | 21 | int getFd(); 22 | uint32_t getEvents(); 23 | uint32_t getRevents(); 24 | bool getInEpoll(); 25 | void setInEpoll(); 26 | 27 | // void setEvents(uint32_t); 28 | void setRevents(uint32_t); 29 | void setCallback(std::function); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /code/day07/src/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Channel; 6 | class Epoll 7 | { 8 | private: 9 | int epfd; 10 | struct epoll_event *events; 11 | public: 12 | Epoll(); 13 | ~Epoll(); 14 | 15 | void addFd(int fd, uint32_t op); 16 | void updateChannel(Channel*); 17 | // std::vector poll(int timeout = -1); 18 | std::vector poll(int timeout = -1); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day07/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "Epoll.h" 3 | #include "Channel.h" 4 | #include 5 | 6 | EventLoop::EventLoop() : ep(nullptr), quit(false){ 7 | ep = new Epoll(); 8 | } 9 | 10 | EventLoop::~EventLoop() 11 | { 12 | delete ep; 13 | } 14 | 15 | 16 | void EventLoop::loop(){ 17 | while(!quit){ 18 | std::vector chs; 19 | chs = ep->poll(); 20 | for(auto it = chs.begin(); it != chs.end(); ++it){ 21 | (*it)->handleEvent(); 22 | } 23 | } 24 | } 25 | 26 | void EventLoop::updateChannel(Channel *ch){ 27 | ep->updateChannel(ch); 28 | } -------------------------------------------------------------------------------- /code/day07/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class Epoll; 3 | class Channel; 4 | class EventLoop 5 | { 6 | private: 7 | Epoll *ep; 8 | bool quit; 9 | public: 10 | EventLoop(); 11 | ~EventLoop(); 12 | 13 | void loop(); 14 | void updateChannel(Channel*); 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /code/day07/src/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | -------------------------------------------------------------------------------- /code/day07/src/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | public: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | InetAddress(); 10 | InetAddress(const char* ip, uint16_t port); 11 | ~InetAddress(); 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /code/day07/src/Server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class EventLoop; 4 | class Socket; 5 | class Acceptor; 6 | class Server 7 | { 8 | private: 9 | EventLoop *loop; 10 | Acceptor *acceptor; 11 | public: 12 | Server(EventLoop*); 13 | ~Server(); 14 | 15 | void handleReadEvent(int); 16 | void newConnection(Socket *serv_sock); 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /code/day07/src/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | 8 | Socket::Socket() : fd(-1){ 9 | fd = socket(AF_INET, SOCK_STREAM, 0); 10 | errif(fd == -1, "socket create error"); 11 | } 12 | Socket::Socket(int _fd) : fd(_fd){ 13 | errif(fd == -1, "socket create error"); 14 | } 15 | 16 | Socket::~Socket(){ 17 | if(fd != -1){ 18 | close(fd); 19 | fd = -1; 20 | } 21 | } 22 | 23 | void Socket::bind(InetAddress *addr){ 24 | errif(::bind(fd, (sockaddr*)&addr->addr, addr->addr_len) == -1, "socket bind error"); 25 | } 26 | 27 | void Socket::listen(){ 28 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 29 | } 30 | void Socket::setnonblocking(){ 31 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 32 | } 33 | 34 | int Socket::accept(InetAddress *addr){ 35 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr->addr, &addr->addr_len); 36 | errif(clnt_sockfd == -1, "socket accept error"); 37 | return clnt_sockfd; 38 | } 39 | 40 | int Socket::getFd(){ 41 | return fd; 42 | } -------------------------------------------------------------------------------- /code/day07/src/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | 19 | int getFd(); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /code/day07/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day07/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day08/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ src/util.cpp client.cpp -o client && \ 3 | g++ server.cpp \ 4 | src/util.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Connection.cpp \ 5 | src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp \ 6 | -o server 7 | clean: 8 | rm server && rm client -------------------------------------------------------------------------------- /code/day08/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "src/util.h" 7 | 8 | #define BUFFER_SIZE 1024 9 | 10 | int main() { 11 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 12 | errif(sockfd == -1, "socket create error"); 13 | 14 | struct sockaddr_in serv_addr; 15 | bzero(&serv_addr, sizeof(serv_addr)); 16 | serv_addr.sin_family = AF_INET; 17 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 18 | serv_addr.sin_port = htons(1234); 19 | 20 | errif(connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) == -1, "socket connect error"); 21 | 22 | while(true){ 23 | char buf[BUFFER_SIZE]; //在这个版本,buf大小必须大于或等于服务器端buf大小,不然会出错,想想为什么? 24 | bzero(&buf, sizeof(buf)); 25 | scanf("%s", buf); 26 | ssize_t write_bytes = write(sockfd, buf, sizeof(buf)); 27 | if(write_bytes == -1){ 28 | printf("socket already disconnected, can't write any more!\n"); 29 | break; 30 | } 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | printf("message from server: %s\n", buf); 35 | }else if(read_bytes == 0){ 36 | printf("server socket disconnected!\n"); 37 | break; 38 | }else if(read_bytes == -1){ 39 | close(sockfd); 40 | errif(true, "socket read error"); 41 | } 42 | } 43 | close(sockfd); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /code/day08/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /code/day08/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "Socket.h" 3 | #include "InetAddress.h" 4 | #include "Channel.h" 5 | 6 | Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){ 7 | sock = new Socket(); 8 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 9 | sock->bind(addr); 10 | sock->listen(); 11 | sock->setnonblocking(); 12 | acceptChannel = new Channel(loop, sock->getFd()); 13 | std::function cb = std::bind(&Acceptor::acceptConnection, this); 14 | acceptChannel->setCallback(cb); 15 | acceptChannel->enableReading(); 16 | delete addr; 17 | } 18 | 19 | Acceptor::~Acceptor(){ 20 | delete sock; 21 | delete acceptChannel; 22 | } 23 | 24 | void Acceptor::acceptConnection(){ 25 | InetAddress *clnt_addr = new InetAddress(); 26 | Socket *clnt_sock = new Socket(sock->accept(clnt_addr)); 27 | 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)); 28 | clnt_sock->setnonblocking(); 29 | newConnectionCallback(clnt_sock); 30 | delete clnt_addr; 31 | } 32 | 33 | void Acceptor::setNewConnectionCallback(std::function _cb){ 34 | newConnectionCallback = _cb; 35 | } -------------------------------------------------------------------------------- /code/day08/src/Acceptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class EventLoop; 5 | class Socket; 6 | class Channel; 7 | class Acceptor 8 | { 9 | private: 10 | EventLoop *loop; 11 | Socket *sock; 12 | Channel *acceptChannel; 13 | std::function newConnectionCallback; 14 | public: 15 | Acceptor(EventLoop *_loop); 16 | ~Acceptor(); 17 | void acceptConnection(); 18 | void setNewConnectionCallback(std::function); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day08/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | #include 4 | 5 | Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){ 6 | 7 | } 8 | 9 | Channel::~Channel(){ 10 | if(fd != -1){ 11 | close(fd); 12 | fd = -1; 13 | } 14 | } 15 | 16 | void Channel::handleEvent(){ 17 | callback(); 18 | } 19 | 20 | void Channel::enableReading(){ 21 | events |= EPOLLIN | EPOLLET; 22 | loop->updateChannel(this); 23 | } 24 | 25 | int Channel::getFd(){ 26 | return fd; 27 | } 28 | 29 | uint32_t Channel::getEvents(){ 30 | return events; 31 | } 32 | uint32_t Channel::getRevents(){ 33 | return revents; 34 | } 35 | 36 | bool Channel::getInEpoll(){ 37 | return inEpoll; 38 | } 39 | 40 | void Channel::setInEpoll(){ 41 | inEpoll = true; 42 | } 43 | 44 | // void Channel::setEvents(uint32_t _ev){ 45 | // events = _ev; 46 | // } 47 | 48 | void Channel::setRevents(uint32_t _ev){ 49 | revents = _ev; 50 | } 51 | 52 | void Channel::setCallback(std::function _cb){ 53 | callback = _cb; 54 | } -------------------------------------------------------------------------------- /code/day08/src/Channel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Channel 6 | { 7 | private: 8 | EventLoop *loop; 9 | int fd; 10 | uint32_t events; 11 | uint32_t revents; 12 | bool inEpoll; 13 | std::function callback; 14 | public: 15 | Channel(EventLoop *_loop, int _fd); 16 | ~Channel(); 17 | 18 | void handleEvent(); 19 | void enableReading(); 20 | 21 | int getFd(); 22 | uint32_t getEvents(); 23 | uint32_t getRevents(); 24 | bool getInEpoll(); 25 | void setInEpoll(); 26 | 27 | // void setEvents(uint32_t); 28 | void setRevents(uint32_t); 29 | void setCallback(std::function); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /code/day08/src/Connection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class EventLoop; 5 | class Socket; 6 | class Channel; 7 | class Connection 8 | { 9 | private: 10 | EventLoop *loop; 11 | Socket *sock; 12 | Channel *channel; 13 | std::function deleteConnectionCallback; 14 | public: 15 | Connection(EventLoop *_loop, Socket *_sock); 16 | ~Connection(); 17 | 18 | void echo(int sockfd); 19 | void setDeleteConnectionCallback(std::function); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /code/day08/src/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Channel; 6 | class Epoll 7 | { 8 | private: 9 | int epfd; 10 | struct epoll_event *events; 11 | public: 12 | Epoll(); 13 | ~Epoll(); 14 | 15 | // void addFd(int fd, uint32_t op); 16 | void updateChannel(Channel*); 17 | // std::vector poll(int timeout = -1); 18 | std::vector poll(int timeout = -1); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day08/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "Epoll.h" 3 | #include "Channel.h" 4 | #include 5 | 6 | EventLoop::EventLoop() : ep(nullptr), quit(false){ 7 | ep = new Epoll(); 8 | } 9 | 10 | EventLoop::~EventLoop() 11 | { 12 | delete ep; 13 | } 14 | 15 | 16 | void EventLoop::loop(){ 17 | while(!quit){ 18 | std::vector chs; 19 | chs = ep->poll(); 20 | for(auto it = chs.begin(); it != chs.end(); ++it){ 21 | (*it)->handleEvent(); 22 | } 23 | } 24 | } 25 | 26 | void EventLoop::updateChannel(Channel *ch){ 27 | ep->updateChannel(ch); 28 | } -------------------------------------------------------------------------------- /code/day08/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Epoll; 4 | class Channel; 5 | class EventLoop 6 | { 7 | private: 8 | Epoll *ep; 9 | bool quit; 10 | public: 11 | EventLoop(); 12 | ~EventLoop(); 13 | 14 | void loop(); 15 | void updateChannel(Channel*); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day08/src/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | 17 | void InetAddress::setInetAddr(sockaddr_in _addr, socklen_t _addr_len){ 18 | addr = _addr; 19 | addr_len = _addr_len; 20 | } 21 | 22 | sockaddr_in InetAddress::getAddr(){ 23 | return addr; 24 | } 25 | socklen_t InetAddress::getAddr_len(){ 26 | return addr_len; 27 | } -------------------------------------------------------------------------------- /code/day08/src/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | private: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | public: 10 | InetAddress(); 11 | InetAddress(const char* ip, uint16_t port); 12 | ~InetAddress(); 13 | void setInetAddr(sockaddr_in _addr, socklen_t _addr_len); 14 | sockaddr_in getAddr(); 15 | socklen_t getAddr_len(); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day08/src/Server.cpp: -------------------------------------------------------------------------------- 1 | #include "Server.h" 2 | #include "Socket.h" 3 | #include "Acceptor.h" 4 | #include "Connection.h" 5 | #include 6 | 7 | 8 | Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){ 9 | acceptor = new Acceptor(loop); 10 | std::function cb = std::bind(&Server::newConnection, this, std::placeholders::_1); 11 | acceptor->setNewConnectionCallback(cb); 12 | } 13 | 14 | Server::~Server(){ 15 | delete acceptor; 16 | } 17 | 18 | 19 | void Server::newConnection(Socket *sock){ 20 | Connection *conn = new Connection(loop, sock); 21 | std::function cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1); 22 | conn->setDeleteConnectionCallback(cb); 23 | connections[sock->getFd()] = conn; 24 | } 25 | 26 | void Server::deleteConnection(Socket * sock){ 27 | Connection *conn = connections[sock->getFd()]; 28 | connections.erase(sock->getFd()); 29 | delete conn; 30 | } -------------------------------------------------------------------------------- /code/day08/src/Server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class EventLoop; 5 | class Socket; 6 | class Acceptor; 7 | class Connection; 8 | class Server 9 | { 10 | private: 11 | EventLoop *loop; 12 | Acceptor *acceptor; 13 | std::map connections; 14 | public: 15 | Server(EventLoop*); 16 | ~Server(); 17 | 18 | void handleReadEvent(int); 19 | void newConnection(Socket *sock); 20 | void deleteConnection(Socket *sock); 21 | }; 22 | 23 | 24 | -------------------------------------------------------------------------------- /code/day08/src/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | Socket::Socket() : fd(-1){ 10 | fd = socket(AF_INET, SOCK_STREAM, 0); 11 | errif(fd == -1, "socket create error"); 12 | } 13 | Socket::Socket(int _fd) : fd(_fd){ 14 | errif(fd == -1, "socket create error"); 15 | } 16 | 17 | Socket::~Socket(){ 18 | if(fd != -1){ 19 | close(fd); 20 | fd = -1; 21 | } 22 | } 23 | 24 | void Socket::bind(InetAddress *_addr){ 25 | struct sockaddr_in addr = _addr->getAddr(); 26 | socklen_t addr_len = _addr->getAddr_len(); 27 | errif(::bind(fd, (sockaddr*)&addr, addr_len) == -1, "socket bind error"); 28 | _addr->setInetAddr(addr, addr_len); 29 | } 30 | 31 | void Socket::listen(){ 32 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 33 | } 34 | void Socket::setnonblocking(){ 35 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 36 | } 37 | 38 | int Socket::accept(InetAddress *_addr){ 39 | struct sockaddr_in addr; 40 | socklen_t addr_len = sizeof(addr); 41 | bzero(&addr, sizeof(addr)); 42 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len); 43 | errif(clnt_sockfd == -1, "socket accept error"); 44 | _addr->setInetAddr(addr, addr_len); 45 | return clnt_sockfd; 46 | } 47 | 48 | int Socket::getFd(){ 49 | return fd; 50 | } -------------------------------------------------------------------------------- /code/day08/src/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int _fd); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | 19 | int getFd(); 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /code/day08/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day08/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day09/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client && \ 3 | g++ server.cpp \ 4 | src/util.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Connection.cpp \ 5 | src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp src/Buffer.cpp \ 6 | -o server 7 | clean: 8 | rm server && rm client -------------------------------------------------------------------------------- /code/day09/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "src/util.h" 5 | #include "src/Buffer.h" 6 | #include "src/InetAddress.h" 7 | #include "src/Socket.h" 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | Socket *sock = new Socket(); 13 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 14 | sock->connect(addr); 15 | 16 | int sockfd = sock->getFd(); 17 | 18 | Buffer *sendBuffer = new Buffer(); 19 | Buffer *readBuffer = new Buffer(); 20 | 21 | while(true){ 22 | sendBuffer->getline(); 23 | ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size()); 24 | if(write_bytes == -1){ 25 | printf("socket already disconnected, can't write any more!\n"); 26 | break; 27 | } 28 | int already_read = 0; 29 | char buf[1024]; //这个buf大小无所谓 30 | while(true){ 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | readBuffer->append(buf, read_bytes); 35 | already_read += read_bytes; 36 | } else if(read_bytes == 0){ //EOF 37 | printf("server disconnected!\n"); 38 | exit(EXIT_SUCCESS); 39 | } 40 | if(already_read >= sendBuffer->size()){ 41 | printf("message from server: %s\n", readBuffer->c_str()); 42 | break; 43 | } 44 | } 45 | readBuffer->clear(); 46 | } 47 | delete addr; 48 | delete sock; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /code/day09/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | delete server; 9 | delete loop; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /code/day09/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "Socket.h" 3 | #include "InetAddress.h" 4 | #include "Channel.h" 5 | 6 | Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){ 7 | sock = new Socket(); 8 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 9 | sock->bind(addr); 10 | sock->listen(); 11 | sock->setnonblocking(); 12 | acceptChannel = new Channel(loop, sock->getFd()); 13 | std::function cb = std::bind(&Acceptor::acceptConnection, this); 14 | acceptChannel->setCallback(cb); 15 | acceptChannel->enableReading(); 16 | delete addr; 17 | } 18 | 19 | Acceptor::~Acceptor(){ 20 | delete sock; 21 | delete acceptChannel; 22 | } 23 | 24 | void Acceptor::acceptConnection(){ 25 | InetAddress *clnt_addr = new InetAddress(); 26 | Socket *clnt_sock = new Socket(sock->accept(clnt_addr)); 27 | 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)); 28 | clnt_sock->setnonblocking(); 29 | newConnectionCallback(clnt_sock); 30 | delete clnt_addr; 31 | } 32 | 33 | void Acceptor::setNewConnectionCallback(std::function _cb){ 34 | newConnectionCallback = _cb; 35 | } -------------------------------------------------------------------------------- /code/day09/src/Acceptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class EventLoop; 5 | class Socket; 6 | class Channel; 7 | class Acceptor 8 | { 9 | private: 10 | EventLoop *loop; 11 | Socket *sock; 12 | Channel *acceptChannel; 13 | std::function newConnectionCallback; 14 | public: 15 | Acceptor(EventLoop *_loop); 16 | ~Acceptor(); 17 | void acceptConnection(); 18 | void setNewConnectionCallback(std::function); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day09/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | #include 3 | #include 4 | Buffer::Buffer() 5 | { 6 | } 7 | 8 | Buffer::~Buffer() 9 | { 10 | } 11 | 12 | 13 | void Buffer::append(const char* _str, int _size){ 14 | for(int i = 0; i < _size; ++i){ 15 | if(_str[i] == '\0') break; 16 | buf.push_back(_str[i]); 17 | } 18 | } 19 | 20 | ssize_t Buffer::size(){ 21 | return buf.size(); 22 | } 23 | 24 | const char* Buffer::c_str(){ 25 | return buf.c_str(); 26 | } 27 | 28 | void Buffer::clear(){ 29 | buf.clear(); 30 | } 31 | 32 | void Buffer::getline(){ 33 | buf.clear(); 34 | std::getline(std::cin, buf); 35 | } -------------------------------------------------------------------------------- /code/day09/src/Buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Buffer 5 | { 6 | private: 7 | std::string buf; 8 | public: 9 | Buffer(); 10 | ~Buffer(); 11 | void append(const char* _str, int _size); 12 | ssize_t size(); 13 | const char* c_str(); 14 | void clear(); 15 | void getline(); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day09/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | #include 4 | 5 | Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){ 6 | 7 | } 8 | 9 | Channel::~Channel(){ 10 | if(fd != -1){ 11 | close(fd); 12 | fd = -1; 13 | } 14 | } 15 | 16 | void Channel::handleEvent(){ 17 | callback(); 18 | } 19 | 20 | void Channel::enableReading(){ 21 | events |= EPOLLIN | EPOLLET; 22 | loop->updateChannel(this); 23 | } 24 | 25 | int Channel::getFd(){ 26 | return fd; 27 | } 28 | 29 | uint32_t Channel::getEvents(){ 30 | return events; 31 | } 32 | uint32_t Channel::getRevents(){ 33 | return revents; 34 | } 35 | 36 | bool Channel::getInEpoll(){ 37 | return inEpoll; 38 | } 39 | 40 | void Channel::setInEpoll(){ 41 | inEpoll = true; 42 | } 43 | 44 | // void Channel::setEvents(uint32_t _ev){ 45 | // events = _ev; 46 | // } 47 | 48 | void Channel::setRevents(uint32_t _ev){ 49 | revents = _ev; 50 | } 51 | 52 | void Channel::setCallback(std::function _cb){ 53 | callback = _cb; 54 | } -------------------------------------------------------------------------------- /code/day09/src/Channel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Channel 6 | { 7 | private: 8 | EventLoop *loop; 9 | int fd; 10 | uint32_t events; 11 | uint32_t revents; 12 | bool inEpoll; 13 | std::function callback; 14 | public: 15 | Channel(EventLoop *_loop, int _fd); 16 | ~Channel(); 17 | 18 | void handleEvent(); 19 | void enableReading(); 20 | 21 | int getFd(); 22 | uint32_t getEvents(); 23 | uint32_t getRevents(); 24 | bool getInEpoll(); 25 | void setInEpoll(); 26 | 27 | // void setEvents(uint32_t); 28 | void setRevents(uint32_t); 29 | void setCallback(std::function); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /code/day09/src/Connection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Socket; 6 | class Channel; 7 | class Buffer; 8 | class Connection 9 | { 10 | private: 11 | EventLoop *loop; 12 | Socket *sock; 13 | Channel *channel; 14 | std::function deleteConnectionCallback; 15 | std::string *inBuffer; 16 | Buffer *readBuffer; 17 | public: 18 | Connection(EventLoop *_loop, Socket *_sock); 19 | ~Connection(); 20 | 21 | void echo(int sockfd); 22 | void setDeleteConnectionCallback(std::function); 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /code/day09/src/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Channel; 6 | class Epoll 7 | { 8 | private: 9 | int epfd; 10 | struct epoll_event *events; 11 | public: 12 | Epoll(); 13 | ~Epoll(); 14 | 15 | // void addFd(int fd, uint32_t op); 16 | void updateChannel(Channel*); 17 | // std::vector poll(int timeout = -1); 18 | std::vector poll(int timeout = -1); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day09/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "Epoll.h" 3 | #include "Channel.h" 4 | #include 5 | 6 | EventLoop::EventLoop() : ep(nullptr), quit(false){ 7 | ep = new Epoll(); 8 | } 9 | 10 | EventLoop::~EventLoop(){ 11 | delete ep; 12 | } 13 | 14 | 15 | void EventLoop::loop(){ 16 | while(!quit){ 17 | std::vector chs; 18 | chs = ep->poll(); 19 | for(auto it = chs.begin(); it != chs.end(); ++it){ 20 | (*it)->handleEvent(); 21 | } 22 | } 23 | } 24 | 25 | void EventLoop::updateChannel(Channel *ch){ 26 | ep->updateChannel(ch); 27 | } -------------------------------------------------------------------------------- /code/day09/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Epoll; 4 | class Channel; 5 | class EventLoop 6 | { 7 | private: 8 | Epoll *ep; 9 | bool quit; 10 | public: 11 | EventLoop(); 12 | ~EventLoop(); 13 | 14 | void loop(); 15 | void updateChannel(Channel*); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day09/src/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | 17 | void InetAddress::setInetAddr(sockaddr_in _addr, socklen_t _addr_len){ 18 | addr = _addr; 19 | addr_len = _addr_len; 20 | } 21 | 22 | sockaddr_in InetAddress::getAddr(){ 23 | return addr; 24 | } 25 | socklen_t InetAddress::getAddr_len(){ 26 | return addr_len; 27 | } -------------------------------------------------------------------------------- /code/day09/src/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | private: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | public: 10 | InetAddress(); 11 | InetAddress(const char* ip, uint16_t port); 12 | ~InetAddress(); 13 | void setInetAddr(sockaddr_in _addr, socklen_t _addr_len); 14 | sockaddr_in getAddr(); 15 | socklen_t getAddr_len(); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day09/src/Server.cpp: -------------------------------------------------------------------------------- 1 | #include "Server.h" 2 | #include "Socket.h" 3 | #include "Acceptor.h" 4 | #include "Connection.h" 5 | #include 6 | 7 | 8 | Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){ 9 | acceptor = new Acceptor(loop); 10 | std::function cb = std::bind(&Server::newConnection, this, std::placeholders::_1); 11 | acceptor->setNewConnectionCallback(cb); 12 | } 13 | 14 | Server::~Server(){ 15 | delete acceptor; 16 | } 17 | 18 | 19 | void Server::newConnection(Socket *sock){ 20 | Connection *conn = new Connection(loop, sock); 21 | std::function cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1); 22 | conn->setDeleteConnectionCallback(cb); 23 | connections[sock->getFd()] = conn; 24 | } 25 | 26 | void Server::deleteConnection(Socket *sock){ 27 | Connection *conn = connections[sock->getFd()]; 28 | connections.erase(sock->getFd()); 29 | delete conn; 30 | } -------------------------------------------------------------------------------- /code/day09/src/Server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class EventLoop; 5 | class Socket; 6 | class Acceptor; 7 | class Connection; 8 | class Server 9 | { 10 | private: 11 | EventLoop *loop; 12 | Acceptor *acceptor; 13 | std::map connections; 14 | public: 15 | Server(EventLoop*); 16 | ~Server(); 17 | 18 | void handleReadEvent(int); 19 | void newConnection(Socket *sock); 20 | void deleteConnection(Socket *sock); 21 | }; 22 | 23 | 24 | -------------------------------------------------------------------------------- /code/day09/src/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | Socket::Socket() : fd(-1){ 10 | fd = socket(AF_INET, SOCK_STREAM, 0); 11 | errif(fd == -1, "socket create error"); 12 | } 13 | Socket::Socket(int _fd) : fd(_fd){ 14 | errif(fd == -1, "socket create error"); 15 | } 16 | 17 | Socket::~Socket(){ 18 | if(fd != -1){ 19 | close(fd); 20 | fd = -1; 21 | } 22 | } 23 | 24 | void Socket::bind(InetAddress *_addr){ 25 | struct sockaddr_in addr = _addr->getAddr(); 26 | socklen_t addr_len = _addr->getAddr_len(); 27 | errif(::bind(fd, (sockaddr*)&addr, addr_len) == -1, "socket bind error"); 28 | _addr->setInetAddr(addr, addr_len); 29 | } 30 | 31 | void Socket::listen(){ 32 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 33 | } 34 | void Socket::setnonblocking(){ 35 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 36 | } 37 | 38 | int Socket::accept(InetAddress *_addr){ 39 | struct sockaddr_in addr; 40 | socklen_t addr_len = sizeof(addr); 41 | bzero(&addr, sizeof(addr)); 42 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len); 43 | errif(clnt_sockfd == -1, "socket accept error"); 44 | _addr->setInetAddr(addr, addr_len); 45 | return clnt_sockfd; 46 | } 47 | void Socket::connect(InetAddress *_addr){ 48 | struct sockaddr_in addr = _addr->getAddr(); 49 | socklen_t addr_len = _addr->getAddr_len(); 50 | errif(::connect(fd, (sockaddr*)&addr, addr_len) == -1, "socket connect error"); 51 | } 52 | 53 | int Socket::getFd(){ 54 | return fd; 55 | } -------------------------------------------------------------------------------- /code/day09/src/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int _fd); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | void connect(InetAddress*); 19 | 20 | int getFd(); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /code/day09/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day09/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day10/Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client && \ 3 | g++ server.cpp \ 4 | -pthread \ 5 | src/util.cpp src/Epoll.cpp src/InetAddress.cpp src/Socket.cpp src/Connection.cpp \ 6 | src/Channel.cpp src/EventLoop.cpp src/Server.cpp src/Acceptor.cpp src/Buffer.cpp \ 7 | src/ThreadPool.cpp \ 8 | -o server 9 | clean: 10 | rm server && rm client 11 | 12 | threadTest: 13 | g++ -pthread src/ThreadPool.cpp ThreadPoolTest.cpp -o ThreadPoolTest -------------------------------------------------------------------------------- /code/day10/ThreadPoolTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "src/ThreadPool.h" 4 | 5 | void print(int a, double b, const char *c, std::string d){ 6 | std::cout << a << b << c << d << std::endl; 7 | } 8 | 9 | void test(){ 10 | std::cout << "hellp" << std::endl; 11 | } 12 | 13 | int main(int argc, char const *argv[]) 14 | { 15 | ThreadPool *poll = new ThreadPool(); 16 | std::function func = std::bind(print, 1, 3.14, "hello", std::string("world")); 17 | poll->add(func); 18 | func = test; 19 | poll->add(func); 20 | delete poll; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /code/day10/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "src/util.h" 5 | #include "src/Buffer.h" 6 | #include "src/InetAddress.h" 7 | #include "src/Socket.h" 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | Socket *sock = new Socket(); 13 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 14 | sock->connect(addr); 15 | 16 | int sockfd = sock->getFd(); 17 | 18 | Buffer *sendBuffer = new Buffer(); 19 | Buffer *readBuffer = new Buffer(); 20 | 21 | while(true){ 22 | sendBuffer->getline(); 23 | ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size()); 24 | if(write_bytes == -1){ 25 | printf("socket already disconnected, can't write any more!\n"); 26 | break; 27 | } 28 | int already_read = 0; 29 | char buf[1024]; //这个buf大小无所谓 30 | while(true){ 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | readBuffer->append(buf, read_bytes); 35 | already_read += read_bytes; 36 | } else if(read_bytes == 0){ //EOF 37 | printf("server disconnected!\n"); 38 | exit(EXIT_SUCCESS); 39 | } 40 | if(already_read >= sendBuffer->size()){ 41 | printf("message from server: %s\n", readBuffer->c_str()); 42 | break; 43 | } 44 | } 45 | readBuffer->clear(); 46 | } 47 | delete addr; 48 | delete sock; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /code/day10/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | delete server; 9 | delete loop; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /code/day10/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | #include "Acceptor.h" 2 | #include "Socket.h" 3 | #include "InetAddress.h" 4 | #include "Channel.h" 5 | 6 | Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){ 7 | sock = new Socket(); 8 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 9 | sock->bind(addr); 10 | sock->listen(); 11 | sock->setnonblocking(); 12 | acceptChannel = new Channel(loop, sock->getFd()); 13 | std::function cb = std::bind(&Acceptor::acceptConnection, this); 14 | acceptChannel->setCallback(cb); 15 | acceptChannel->enableReading(); 16 | delete addr; 17 | } 18 | 19 | Acceptor::~Acceptor(){ 20 | delete sock; 21 | delete acceptChannel; 22 | } 23 | 24 | void Acceptor::acceptConnection(){ 25 | InetAddress *clnt_addr = new InetAddress(); 26 | Socket *clnt_sock = new Socket(sock->accept(clnt_addr)); 27 | 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)); 28 | clnt_sock->setnonblocking(); 29 | newConnectionCallback(clnt_sock); 30 | delete clnt_addr; 31 | } 32 | 33 | void Acceptor::setNewConnectionCallback(std::function _cb){ 34 | newConnectionCallback = _cb; 35 | } -------------------------------------------------------------------------------- /code/day10/src/Acceptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Socket; 6 | class Channel; 7 | class Acceptor 8 | { 9 | private: 10 | EventLoop *loop; 11 | Socket *sock; 12 | Channel *acceptChannel; 13 | std::function newConnectionCallback; 14 | public: 15 | Acceptor(EventLoop *_loop); 16 | ~Acceptor(); 17 | void acceptConnection(); 18 | void setNewConnectionCallback(std::function); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day10/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | #include 3 | #include 4 | Buffer::Buffer() 5 | { 6 | } 7 | 8 | Buffer::~Buffer() 9 | { 10 | } 11 | 12 | 13 | void Buffer::append(const char* _str, int _size){ 14 | for(int i = 0; i < _size; ++i){ 15 | if(_str[i] == '\0') break; 16 | buf.push_back(_str[i]); 17 | } 18 | } 19 | 20 | ssize_t Buffer::size(){ 21 | return buf.size(); 22 | } 23 | 24 | const char* Buffer::c_str(){ 25 | return buf.c_str(); 26 | } 27 | 28 | void Buffer::clear(){ 29 | buf.clear(); 30 | } 31 | 32 | void Buffer::getline(){ 33 | buf.clear(); 34 | std::getline(std::cin, buf); 35 | } -------------------------------------------------------------------------------- /code/day10/src/Buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Buffer 5 | { 6 | private: 7 | std::string buf; 8 | public: 9 | Buffer(); 10 | ~Buffer(); 11 | void append(const char* _str, int _size); 12 | ssize_t size(); 13 | const char* c_str(); 14 | void clear(); 15 | void getline(); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day10/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | #include "Channel.h" 2 | #include "EventLoop.h" 3 | #include 4 | 5 | Channel::Channel(EventLoop *_loop, int _fd) : loop(_loop), fd(_fd), events(0), revents(0), inEpoll(false){ 6 | 7 | } 8 | 9 | Channel::~Channel(){ 10 | if(fd != -1){ 11 | close(fd); 12 | fd = -1; 13 | } 14 | } 15 | 16 | void Channel::handleEvent(){ 17 | loop->addThread(callback); 18 | // callback(); 19 | } 20 | 21 | void Channel::enableReading(){ 22 | events |= EPOLLIN | EPOLLET; 23 | loop->updateChannel(this); 24 | } 25 | 26 | int Channel::getFd(){ 27 | return fd; 28 | } 29 | 30 | uint32_t Channel::getEvents(){ 31 | return events; 32 | } 33 | uint32_t Channel::getRevents(){ 34 | return revents; 35 | } 36 | 37 | bool Channel::getInEpoll(){ 38 | return inEpoll; 39 | } 40 | 41 | void Channel::setInEpoll(){ 42 | inEpoll = true; 43 | } 44 | 45 | // void Channel::setEvents(uint32_t _ev){ 46 | // events = _ev; 47 | // } 48 | 49 | void Channel::setRevents(uint32_t _ev){ 50 | revents = _ev; 51 | } 52 | 53 | void Channel::setCallback(std::function _cb){ 54 | callback = _cb; 55 | } -------------------------------------------------------------------------------- /code/day10/src/Channel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Channel 6 | { 7 | private: 8 | EventLoop *loop; 9 | int fd; 10 | uint32_t events; 11 | uint32_t revents; 12 | bool inEpoll; 13 | std::function callback; 14 | public: 15 | Channel(EventLoop *_loop, int _fd); 16 | ~Channel(); 17 | 18 | void handleEvent(); 19 | void enableReading(); 20 | 21 | int getFd(); 22 | uint32_t getEvents(); 23 | uint32_t getRevents(); 24 | bool getInEpoll(); 25 | void setInEpoll(); 26 | 27 | // void setEvents(uint32_t); 28 | void setRevents(uint32_t); 29 | void setCallback(std::function); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /code/day10/src/Connection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class EventLoop; 5 | class Socket; 6 | class Channel; 7 | class Buffer; 8 | class Connection 9 | { 10 | private: 11 | EventLoop *loop; 12 | Socket *sock; 13 | Channel *channel; 14 | std::function deleteConnectionCallback; 15 | std::string *inBuffer; 16 | Buffer *readBuffer; 17 | public: 18 | Connection(EventLoop *_loop, Socket *_sock); 19 | ~Connection(); 20 | 21 | void echo(int sockfd); 22 | void setDeleteConnectionCallback(std::function); 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /code/day10/src/Epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class Channel; 6 | class Epoll 7 | { 8 | private: 9 | int epfd; 10 | struct epoll_event *events; 11 | public: 12 | Epoll(); 13 | ~Epoll(); 14 | 15 | // void addFd(int fd, uint32_t op); 16 | void updateChannel(Channel*); 17 | // std::vector poll(int timeout = -1); 18 | std::vector poll(int timeout = -1); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /code/day10/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "Epoll.h" 3 | #include "Channel.h" 4 | #include "ThreadPool.h" 5 | #include 6 | 7 | EventLoop::EventLoop() : ep(nullptr), threadPool(nullptr), quit(false){ 8 | ep = new Epoll(); 9 | threadPool = new ThreadPool(); 10 | } 11 | 12 | EventLoop::~EventLoop(){ 13 | delete ep; 14 | } 15 | 16 | 17 | void EventLoop::loop(){ 18 | while(!quit){ 19 | std::vector chs; 20 | chs = ep->poll(); 21 | for(auto it = chs.begin(); it != chs.end(); ++it){ 22 | (*it)->handleEvent(); 23 | } 24 | } 25 | } 26 | 27 | void EventLoop::updateChannel(Channel *ch){ 28 | ep->updateChannel(ch); 29 | } 30 | 31 | void EventLoop::addThread(std::function func){ 32 | threadPool->add(func); 33 | } -------------------------------------------------------------------------------- /code/day10/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Epoll; 5 | class Channel; 6 | class ThreadPool; 7 | class EventLoop 8 | { 9 | private: 10 | Epoll *ep; 11 | ThreadPool *threadPool; 12 | bool quit; 13 | public: 14 | EventLoop(); 15 | ~EventLoop(); 16 | 17 | void loop(); 18 | void updateChannel(Channel*); 19 | 20 | void addThread(std::function); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /code/day10/src/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | #include "InetAddress.h" 2 | #include 3 | InetAddress::InetAddress() : addr_len(sizeof(addr)){ 4 | bzero(&addr, sizeof(addr)); 5 | } 6 | InetAddress::InetAddress(const char* ip, uint16_t port) : addr_len(sizeof(addr)){ 7 | bzero(&addr, sizeof(addr)); 8 | addr.sin_family = AF_INET; 9 | addr.sin_addr.s_addr = inet_addr(ip); 10 | addr.sin_port = htons(port); 11 | addr_len = sizeof(addr); 12 | } 13 | 14 | InetAddress::~InetAddress(){ 15 | } 16 | 17 | void InetAddress::setInetAddr(sockaddr_in _addr, socklen_t _addr_len){ 18 | addr = _addr; 19 | addr_len = _addr_len; 20 | } 21 | 22 | sockaddr_in InetAddress::getAddr(){ 23 | return addr; 24 | } 25 | socklen_t InetAddress::getAddr_len(){ 26 | return addr_len; 27 | } -------------------------------------------------------------------------------- /code/day10/src/InetAddress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class InetAddress 5 | { 6 | private: 7 | struct sockaddr_in addr; 8 | socklen_t addr_len; 9 | public: 10 | InetAddress(); 11 | InetAddress(const char* ip, uint16_t port); 12 | ~InetAddress(); 13 | void setInetAddr(sockaddr_in _addr, socklen_t _addr_len); 14 | sockaddr_in getAddr(); 15 | socklen_t getAddr_len(); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /code/day10/src/Server.cpp: -------------------------------------------------------------------------------- 1 | #include "Server.h" 2 | #include "Socket.h" 3 | #include "Acceptor.h" 4 | #include "Connection.h" 5 | #include 6 | 7 | 8 | Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){ 9 | acceptor = new Acceptor(loop); 10 | std::function cb = std::bind(&Server::newConnection, this, std::placeholders::_1); 11 | acceptor->setNewConnectionCallback(cb); 12 | } 13 | 14 | Server::~Server(){ 15 | delete acceptor; 16 | } 17 | 18 | 19 | void Server::newConnection(Socket *sock){ 20 | Connection *conn = new Connection(loop, sock); 21 | std::function cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1); 22 | conn->setDeleteConnectionCallback(cb); 23 | connections[sock->getFd()] = conn; 24 | } 25 | 26 | void Server::deleteConnection(Socket *sock){ 27 | Connection *conn = connections[sock->getFd()]; 28 | connections.erase(sock->getFd()); 29 | delete conn; 30 | } -------------------------------------------------------------------------------- /code/day10/src/Server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class EventLoop; 5 | class Socket; 6 | class Acceptor; 7 | class Connection; 8 | class Server 9 | { 10 | private: 11 | EventLoop *loop; 12 | Acceptor *acceptor; 13 | std::map connections; 14 | public: 15 | Server(EventLoop*); 16 | ~Server(); 17 | 18 | void handleReadEvent(int); 19 | void newConnection(Socket *sock); 20 | void deleteConnection(Socket *sock); 21 | }; 22 | 23 | 24 | -------------------------------------------------------------------------------- /code/day10/src/Socket.cpp: -------------------------------------------------------------------------------- 1 | #include "Socket.h" 2 | #include "InetAddress.h" 3 | #include "util.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | Socket::Socket() : fd(-1){ 10 | fd = socket(AF_INET, SOCK_STREAM, 0); 11 | errif(fd == -1, "socket create error"); 12 | } 13 | Socket::Socket(int _fd) : fd(_fd){ 14 | errif(fd == -1, "socket create error"); 15 | } 16 | 17 | Socket::~Socket(){ 18 | if(fd != -1){ 19 | close(fd); 20 | fd = -1; 21 | } 22 | } 23 | 24 | void Socket::bind(InetAddress *_addr){ 25 | struct sockaddr_in addr = _addr->getAddr(); 26 | socklen_t addr_len = _addr->getAddr_len(); 27 | errif(::bind(fd, (sockaddr*)&addr, addr_len) == -1, "socket bind error"); 28 | _addr->setInetAddr(addr, addr_len); 29 | } 30 | 31 | void Socket::listen(){ 32 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 33 | } 34 | void Socket::setnonblocking(){ 35 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 36 | } 37 | 38 | int Socket::accept(InetAddress *_addr){ 39 | struct sockaddr_in addr; 40 | socklen_t addr_len = sizeof(addr); 41 | bzero(&addr, sizeof(addr)); 42 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len); 43 | errif(clnt_sockfd == -1, "socket accept error"); 44 | _addr->setInetAddr(addr, addr_len); 45 | return clnt_sockfd; 46 | } 47 | void Socket::connect(InetAddress *_addr){ 48 | struct sockaddr_in addr = _addr->getAddr(); 49 | socklen_t addr_len = _addr->getAddr_len(); 50 | errif(::connect(fd, (sockaddr*)&addr, addr_len) == -1, "socket connect error"); 51 | } 52 | 53 | int Socket::getFd(){ 54 | return fd; 55 | } -------------------------------------------------------------------------------- /code/day10/src/Socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InetAddress; 4 | class Socket 5 | { 6 | private: 7 | int fd; 8 | public: 9 | Socket(); 10 | Socket(int _fd); 11 | ~Socket(); 12 | 13 | void bind(InetAddress*); 14 | void listen(); 15 | void setnonblocking(); 16 | 17 | int accept(InetAddress*); 18 | void connect(InetAddress*); 19 | 20 | int getFd(); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /code/day10/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "ThreadPool.h" 2 | 3 | ThreadPool::ThreadPool(int size) : stop(false){ 4 | for(int i = 0; i < size; ++i){ 5 | threads.emplace_back(std::thread([this](){ 6 | while(true){ 7 | std::function task; 8 | { 9 | std::unique_lock lock(tasks_mtx); 10 | cv.wait(lock, [this](){ 11 | return stop || !tasks.empty(); 12 | }); 13 | if(stop && tasks.empty()) return; 14 | task = tasks.front(); 15 | tasks.pop(); 16 | } 17 | task(); 18 | } 19 | })); 20 | } 21 | } 22 | 23 | ThreadPool::~ThreadPool(){ 24 | { 25 | std::unique_lock lock(tasks_mtx); 26 | stop = true; 27 | } 28 | cv.notify_all(); 29 | for(std::thread &th : threads){ 30 | if(th.joinable()) 31 | th.join(); 32 | } 33 | } 34 | 35 | void ThreadPool::add(std::function func){ 36 | { 37 | std::unique_lock lock(tasks_mtx); 38 | if(stop) 39 | throw std::runtime_error("ThreadPool already stop, can't add task any more"); 40 | tasks.emplace(func); 41 | } 42 | cv.notify_one(); 43 | } 44 | -------------------------------------------------------------------------------- /code/day10/src/ThreadPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class ThreadPool 10 | { 11 | private: 12 | std::vector threads; 13 | std::queue> tasks; 14 | std::mutex tasks_mtx; 15 | std::condition_variable cv; 16 | bool stop; 17 | public: 18 | ThreadPool(int size = 10); 19 | ~ThreadPool(); 20 | 21 | void add(std::function); 22 | 23 | }; 24 | -------------------------------------------------------------------------------- /code/day10/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day10/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day11/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/server", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${fileDirname}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": true 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /code/day11/Makefile: -------------------------------------------------------------------------------- 1 | src=$(wildcard src/*.cpp) 2 | 3 | server: 4 | g++ -std=c++11 -pthread -g \ 5 | $(src) \ 6 | server.cpp \ 7 | -o server 8 | 9 | client: 10 | g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp client.cpp -o client 11 | 12 | th: 13 | g++ -pthread src/ThreadPool.cpp ThreadPoolTest.cpp -o ThreadPoolTest 14 | 15 | test: 16 | g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/InetAddress.cpp src/ThreadPool.cpp \ 17 | -pthread \ 18 | test.cpp -o test 19 | 20 | clean: 21 | rm server && rm client && rm test -------------------------------------------------------------------------------- /code/day11/ThreadPoolTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "src/ThreadPool.h" 4 | 5 | void print(int a, double b, const char *c, std::string d){ 6 | std::cout << a << b << c << d << std::endl; 7 | } 8 | 9 | void test(){ 10 | std::cout << "hellp" << std::endl; 11 | } 12 | 13 | int main(int argc, char const *argv[]) 14 | { 15 | ThreadPool *poll = new ThreadPool(); 16 | std::function func = std::bind(print, 1, 3.14, "hello", std::string("world")); 17 | poll->add(func); 18 | func = test; 19 | poll->add(func); 20 | delete poll; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /code/day11/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "src/util.h" 5 | #include "src/Buffer.h" 6 | #include "src/InetAddress.h" 7 | #include "src/Socket.h" 8 | 9 | using namespace std; 10 | 11 | int main() { 12 | Socket *sock = new Socket(); 13 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 14 | sock->connect(addr); 15 | 16 | int sockfd = sock->getFd(); 17 | 18 | Buffer *sendBuffer = new Buffer(); 19 | Buffer *readBuffer = new Buffer(); 20 | 21 | while(true){ 22 | sendBuffer->getline(); 23 | ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size()); 24 | if(write_bytes == -1){ 25 | printf("socket already disconnected, can't write any more!\n"); 26 | break; 27 | } 28 | int already_read = 0; 29 | char buf[1024]; //这个buf大小无所谓 30 | while(true){ 31 | bzero(&buf, sizeof(buf)); 32 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 33 | if(read_bytes > 0){ 34 | readBuffer->append(buf, read_bytes); 35 | already_read += read_bytes; 36 | } else if(read_bytes == 0){ //EOF 37 | printf("server disconnected!\n"); 38 | exit(EXIT_SUCCESS); 39 | } 40 | if(already_read >= sendBuffer->size()){ 41 | printf("message from server: %s\n", readBuffer->c_str()); 42 | break; 43 | } 44 | } 45 | readBuffer->clear(); 46 | } 47 | delete addr; 48 | delete sock; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /code/day11/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /code/day11/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Acceptor.h" 8 | #include "Socket.h" 9 | #include "InetAddress.h" 10 | #include "Channel.h" 11 | 12 | Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){ 13 | sock = new Socket(); 14 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 15 | sock->bind(addr); 16 | // sock->setnonblocking(); 17 | sock->listen(); 18 | acceptChannel = new Channel(loop, sock->getFd()); 19 | std::function cb = std::bind(&Acceptor::acceptConnection, this); 20 | acceptChannel->setReadCallback(cb); 21 | acceptChannel->enableRead(); 22 | acceptChannel->setUseThreadPool(false); 23 | delete addr; 24 | } 25 | 26 | Acceptor::~Acceptor(){ 27 | delete sock; 28 | delete acceptChannel; 29 | } 30 | 31 | void Acceptor::acceptConnection(){ 32 | InetAddress *clnt_addr = new InetAddress(); 33 | Socket *clnt_sock = new Socket(sock->accept(clnt_addr)); 34 | 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)); 35 | clnt_sock->setnonblocking(); 36 | newConnectionCallback(clnt_sock); 37 | delete clnt_addr; 38 | } 39 | 40 | void Acceptor::setNewConnectionCallback(std::function _cb){ 41 | newConnectionCallback = _cb; 42 | } -------------------------------------------------------------------------------- /code/day11/src/Acceptor.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | 10 | class EventLoop; 11 | class Socket; 12 | class Channel; 13 | class Acceptor 14 | { 15 | private: 16 | EventLoop *loop; 17 | Socket *sock; 18 | Channel *acceptChannel; 19 | std::function newConnectionCallback; 20 | public: 21 | Acceptor(EventLoop *_loop); 22 | ~Acceptor(); 23 | void acceptConnection(); 24 | void setNewConnectionCallback(std::function); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /code/day11/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Buffer.h" 8 | #include 9 | #include 10 | Buffer::Buffer() {} 11 | 12 | Buffer::~Buffer() {} 13 | 14 | void Buffer::append(const char* _str, int _size){ 15 | for(int i = 0; i < _size; ++i){ 16 | if(_str[i] == '\0') break; 17 | buf.push_back(_str[i]); 18 | } 19 | } 20 | 21 | ssize_t Buffer::size(){ 22 | return buf.size(); 23 | } 24 | 25 | const char* Buffer::c_str(){ 26 | return buf.c_str(); 27 | } 28 | 29 | void Buffer::clear(){ 30 | buf.clear(); 31 | } 32 | 33 | void Buffer::getline(){ 34 | buf.clear(); 35 | std::getline(std::cin, buf); 36 | } 37 | 38 | void Buffer::setBuf(const char* _buf){ 39 | buf.clear(); 40 | buf.append(_buf); 41 | } -------------------------------------------------------------------------------- /code/day11/src/Buffer.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | 10 | class Buffer 11 | { 12 | private: 13 | std::string buf; 14 | public: 15 | Buffer(); 16 | ~Buffer(); 17 | 18 | void append(const char* _str, int _size); 19 | ssize_t size(); 20 | const char* c_str(); 21 | void clear(); 22 | void getline(); 23 | void setBuf(const char*); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /code/day11/src/Channel.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | class Socket; 10 | class EventLoop; 11 | class Channel 12 | { 13 | private: 14 | EventLoop *loop; 15 | int fd; 16 | uint32_t events; 17 | uint32_t ready; 18 | bool inEpoll; 19 | bool useThreadPool; 20 | std::function readCallback; 21 | std::function writeCallback; 22 | public: 23 | Channel(EventLoop *_loop, int _fd); 24 | ~Channel(); 25 | 26 | void handleEvent(); 27 | void enableRead(); 28 | 29 | int getFd(); 30 | uint32_t getEvents(); 31 | uint32_t getReady(); 32 | bool getInEpoll(); 33 | void setInEpoll(bool _in = true); 34 | void useET(); 35 | 36 | void setReady(uint32_t); 37 | void setReadCallback(std::function); 38 | void setUseThreadPool(bool use = true); 39 | }; 40 | 41 | -------------------------------------------------------------------------------- /code/day11/src/Connection.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | #include 10 | class EventLoop; 11 | class Socket; 12 | class Channel; 13 | class Buffer; 14 | class Connection 15 | { 16 | private: 17 | EventLoop *loop; 18 | Socket *sock; 19 | Channel *channel; 20 | std::function deleteConnectionCallback; 21 | std::string *inBuffer; 22 | Buffer *readBuffer; 23 | public: 24 | Connection(EventLoop *_loop, Socket *_sock); 25 | ~Connection(); 26 | 27 | void echo(int sockfd); 28 | void setDeleteConnectionCallback(std::function); 29 | void send(int sockfd); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /code/day11/src/Epoll.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | #include 10 | 11 | class Channel; 12 | class Epoll 13 | { 14 | private: 15 | int epfd; 16 | struct epoll_event *events; 17 | public: 18 | Epoll(); 19 | ~Epoll(); 20 | 21 | void updateChannel(Channel*); 22 | void deleteChannel(Channel*); 23 | 24 | std::vector poll(int timeout = -1); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /code/day11/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "EventLoop.h" 8 | #include "Epoll.h" 9 | #include "Channel.h" 10 | #include "ThreadPool.h" 11 | #include 12 | 13 | EventLoop::EventLoop() : ep(nullptr), threadPool(nullptr), quit(false){ 14 | ep = new Epoll(); 15 | threadPool = new ThreadPool(); 16 | } 17 | 18 | EventLoop::~EventLoop(){ 19 | delete threadPool; 20 | delete ep; 21 | } 22 | 23 | 24 | void EventLoop::loop(){ 25 | while(!quit){ 26 | std::vector chs; 27 | chs = ep->poll(); 28 | for(auto it = chs.begin(); it != chs.end(); ++it){ 29 | (*it)->handleEvent(); 30 | } 31 | } 32 | } 33 | 34 | void EventLoop::updateChannel(Channel *ch){ 35 | ep->updateChannel(ch); 36 | } 37 | 38 | void EventLoop::addThread(std::function func){ 39 | threadPool->add(func); 40 | } -------------------------------------------------------------------------------- /code/day11/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | /****************************** 8 | * author: yuesong-feng 9 | * 10 | * 11 | * 12 | ******************************/ 13 | #pragma once 14 | #include 15 | 16 | class Epoll; 17 | class Channel; 18 | class ThreadPool; 19 | class EventLoop 20 | { 21 | private: 22 | Epoll *ep; 23 | ThreadPool *threadPool; 24 | bool quit; 25 | public: 26 | EventLoop(); 27 | ~EventLoop(); 28 | 29 | void loop(); 30 | void updateChannel(Channel*); 31 | 32 | void addThread(std::function); 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /code/day11/src/InetAddress.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "InetAddress.h" 8 | #include 9 | 10 | InetAddress::InetAddress() { 11 | bzero(&addr, sizeof(addr)); 12 | } 13 | InetAddress::InetAddress(const char* _ip, uint16_t _port) { 14 | bzero(&addr, sizeof(addr)); 15 | addr.sin_family = AF_INET; 16 | addr.sin_addr.s_addr = inet_addr(_ip); 17 | addr.sin_port = htons(_port); 18 | } 19 | 20 | InetAddress::~InetAddress(){ 21 | } 22 | 23 | void InetAddress::setInetAddr(sockaddr_in _addr){ 24 | addr = _addr; 25 | } 26 | 27 | sockaddr_in InetAddress::getAddr(){ 28 | return addr; 29 | } 30 | -------------------------------------------------------------------------------- /code/day11/src/InetAddress.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | 10 | class InetAddress 11 | { 12 | private: 13 | struct sockaddr_in addr; 14 | public: 15 | InetAddress(); 16 | InetAddress(const char* _ip, uint16_t _port); 17 | ~InetAddress(); 18 | 19 | void setInetAddr(sockaddr_in _addr); 20 | sockaddr_in getAddr(); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /code/day11/src/Server.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Server.h" 8 | #include "Socket.h" 9 | #include "Acceptor.h" 10 | #include "Connection.h" 11 | #include 12 | #include 13 | 14 | Server::Server(EventLoop *_loop) : loop(_loop), acceptor(nullptr){ 15 | acceptor = new Acceptor(loop); 16 | std::function cb = std::bind(&Server::newConnection, this, std::placeholders::_1); 17 | acceptor->setNewConnectionCallback(cb); 18 | } 19 | 20 | Server::~Server(){ 21 | delete acceptor; 22 | } 23 | 24 | 25 | void Server::newConnection(Socket *sock){ 26 | if(sock->getFd() != -1){ 27 | Connection *conn = new Connection(loop, sock); 28 | std::function cb = std::bind(&Server::deleteConnection, this, std::placeholders::_1); 29 | conn->setDeleteConnectionCallback(cb); 30 | connections[sock->getFd()] = conn; 31 | } 32 | } 33 | 34 | void Server::deleteConnection(int sockfd){ 35 | if(sockfd != -1){ 36 | auto it = connections.find(sockfd); 37 | if(it != connections.end()){ 38 | Connection *conn = connections[sockfd]; 39 | connections.erase(sockfd); 40 | // close(sockfd); //正常 41 | delete conn; //会Segmant fault 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /code/day11/src/Server.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | class EventLoop; 10 | class Socket; 11 | class Acceptor; 12 | class Connection; 13 | class Server 14 | { 15 | private: 16 | EventLoop *loop; 17 | Acceptor *acceptor; 18 | std::map connections; 19 | public: 20 | Server(EventLoop*); 21 | ~Server(); 22 | 23 | void handleReadEvent(int); 24 | void newConnection(Socket *sock); 25 | void deleteConnection(int sockfd); 26 | }; 27 | 28 | 29 | -------------------------------------------------------------------------------- /code/day11/src/Socket.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Socket.h" 8 | #include "InetAddress.h" 9 | #include "util.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | Socket::Socket() : fd(-1){ 16 | fd = socket(AF_INET, SOCK_STREAM, 0); 17 | errif(fd == -1, "socket create error"); 18 | } 19 | Socket::Socket(int _fd) : fd(_fd){ 20 | errif(fd == -1, "socket create error"); 21 | } 22 | 23 | Socket::~Socket(){ 24 | if(fd != -1){ 25 | close(fd); 26 | fd = -1; 27 | } 28 | } 29 | 30 | void Socket::bind(InetAddress *_addr){ 31 | struct sockaddr_in addr = _addr->getAddr(); 32 | errif(::bind(fd, (sockaddr*)&addr, sizeof(addr)) == -1, "socket bind error"); 33 | } 34 | 35 | void Socket::listen(){ 36 | errif(::listen(fd, SOMAXCONN) == -1, "socket listen error"); 37 | } 38 | void Socket::setnonblocking(){ 39 | fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 40 | } 41 | 42 | int Socket::accept(InetAddress *_addr){ 43 | struct sockaddr_in addr; 44 | bzero(&addr, sizeof(addr)); 45 | socklen_t addr_len = sizeof(addr); 46 | int clnt_sockfd = ::accept(fd, (sockaddr*)&addr, &addr_len); 47 | errif(clnt_sockfd == -1, "socket accept error"); 48 | _addr->setInetAddr(addr); 49 | return clnt_sockfd; 50 | } 51 | 52 | void Socket::connect(InetAddress *_addr){ 53 | struct sockaddr_in addr = _addr->getAddr(); 54 | errif(::connect(fd, (sockaddr*)&addr, sizeof(addr)) == -1, "socket connect error"); 55 | } 56 | 57 | int Socket::getFd(){ 58 | return fd; 59 | } -------------------------------------------------------------------------------- /code/day11/src/Socket.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | 8 | #pragma once 9 | 10 | class InetAddress; 11 | class Socket 12 | { 13 | private: 14 | int fd; 15 | public: 16 | Socket(); 17 | Socket(int _fd); 18 | ~Socket(); 19 | 20 | void bind(InetAddress*); 21 | void listen(); 22 | int accept(InetAddress*); 23 | 24 | void connect(InetAddress*); 25 | 26 | void setnonblocking(); 27 | int getFd(); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /code/day11/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "ThreadPool.h" 8 | 9 | ThreadPool::ThreadPool(int size) : stop(false){ 10 | for(int i = 0; i < size; ++i){ 11 | threads.emplace_back(std::thread([this](){ 12 | while(true){ 13 | std::function task; 14 | { 15 | std::unique_lock lock(tasks_mtx); 16 | cv.wait(lock, [this](){ 17 | return stop || !tasks.empty(); 18 | }); 19 | if(stop && tasks.empty()) return; 20 | task = tasks.front(); 21 | tasks.pop(); 22 | } 23 | task(); 24 | } 25 | })); 26 | } 27 | } 28 | 29 | ThreadPool::~ThreadPool(){ 30 | { 31 | std::unique_lock lock(tasks_mtx); 32 | stop = true; 33 | } 34 | cv.notify_all(); 35 | for(std::thread &th : threads){ 36 | if(th.joinable()) 37 | th.join(); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /code/day11/src/ThreadPool.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class ThreadPool 17 | { 18 | private: 19 | std::vector threads; 20 | std::queue> tasks; 21 | std::mutex tasks_mtx; 22 | std::condition_variable cv; 23 | bool stop; 24 | public: 25 | ThreadPool(int size = 10); 26 | ~ThreadPool(); 27 | 28 | // void add(std::function); 29 | template 30 | auto add(F&& f, Args&&... args) 31 | -> std::future::type>; 32 | 33 | }; 34 | 35 | 36 | //不能放在cpp文件,原因是C++编译器不支持模版的分离编译 37 | template 38 | auto ThreadPool::add(F&& f, Args&&... args) -> std::future::type> { 39 | using return_type = typename std::result_of::type; 40 | 41 | auto task = std::make_shared< std::packaged_task >( 42 | std::bind(std::forward(f), std::forward(args)...) 43 | ); 44 | 45 | std::future res = task->get_future(); 46 | { 47 | std::unique_lock lock(tasks_mtx); 48 | 49 | // don't allow enqueueing after stopping the pool 50 | if(stop) 51 | throw std::runtime_error("enqueue on stopped ThreadPool"); 52 | 53 | tasks.emplace([task](){ (*task)(); }); 54 | } 55 | cv.notify_one(); 56 | return res; 57 | } 58 | -------------------------------------------------------------------------------- /code/day11/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day11/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day12/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/server", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${fileDirname}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": true 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /code/day12/Makefile: -------------------------------------------------------------------------------- 1 | src=$(wildcard src/*.cpp) 2 | 3 | server: 4 | g++ -std=c++11 -pthread -g \ 5 | $(src) \ 6 | server.cpp \ 7 | -o server 8 | 9 | client: 10 | g++ src/util.cpp src/Buffer.cpp src/Socket.cpp client.cpp -o client 11 | 12 | th: 13 | g++ -pthread src/ThreadPool.cpp ThreadPoolTest.cpp -o ThreadPoolTest 14 | 15 | test: 16 | g++ src/util.cpp src/Buffer.cpp src/Socket.cpp src/ThreadPool.cpp \ 17 | -pthread \ 18 | test.cpp -o test 19 | 20 | clean: 21 | rm server && rm client && rm test -------------------------------------------------------------------------------- /code/day12/ThreadPoolTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "src/ThreadPool.h" 4 | 5 | void print(int a, double b, const char *c, std::string d){ 6 | std::cout << a << b << c << d << std::endl; 7 | } 8 | 9 | void test(){ 10 | std::cout << "hellp" << std::endl; 11 | } 12 | 13 | int main(int argc, char const *argv[]) 14 | { 15 | ThreadPool *poll = new ThreadPool(); 16 | std::function func = std::bind(print, 1, 3.14, "hello", std::string("world")); 17 | poll->add(func); 18 | func = test; 19 | poll->add(func); 20 | delete poll; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /code/day12/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "src/util.h" 5 | #include "src/Buffer.h" 6 | #include "src/Socket.h" 7 | 8 | using namespace std; 9 | 10 | int main() { 11 | Socket *sock = new Socket(); 12 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 13 | sock->connect(addr); 14 | 15 | int sockfd = sock->getFd(); 16 | 17 | Buffer *sendBuffer = new Buffer(); 18 | Buffer *readBuffer = new Buffer(); 19 | 20 | while(true){ 21 | sendBuffer->getline(); 22 | ssize_t write_bytes = write(sockfd, sendBuffer->c_str(), sendBuffer->size()); 23 | if(write_bytes == -1){ 24 | printf("socket already disconnected, can't write any more!\n"); 25 | break; 26 | } 27 | int already_read = 0; 28 | char buf[1024]; //这个buf大小无所谓 29 | while(true){ 30 | bzero(&buf, sizeof(buf)); 31 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 32 | if(read_bytes > 0){ 33 | readBuffer->append(buf, read_bytes); 34 | already_read += read_bytes; 35 | } else if(read_bytes == 0){ //EOF 36 | printf("server disconnected!\n"); 37 | exit(EXIT_SUCCESS); 38 | } 39 | if(already_read >= sendBuffer->size()){ 40 | printf("message from server: %s\n", readBuffer->c_str()); 41 | break; 42 | } 43 | } 44 | readBuffer->clear(); 45 | } 46 | delete addr; 47 | delete sock; 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /code/day12/server.cpp: -------------------------------------------------------------------------------- 1 | #include "src/EventLoop.h" 2 | #include "src/Server.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | loop->loop(); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /code/day12/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Acceptor.h" 8 | #include "Socket.h" 9 | #include "Channel.h" 10 | 11 | Acceptor::Acceptor(EventLoop *_loop) : loop(_loop), sock(nullptr), acceptChannel(nullptr){ 12 | sock = new Socket(); 13 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 14 | sock->bind(addr); 15 | // sock->setnonblocking(); acceptor使用阻塞式IO比较好 16 | sock->listen(); 17 | acceptChannel = new Channel(loop, sock->getFd()); 18 | std::function cb = std::bind(&Acceptor::acceptConnection, this); 19 | acceptChannel->setReadCallback(cb); 20 | acceptChannel->enableRead(); 21 | delete addr; 22 | } 23 | 24 | Acceptor::~Acceptor(){ 25 | delete sock; 26 | delete acceptChannel; 27 | } 28 | 29 | void Acceptor::acceptConnection(){ 30 | InetAddress *clnt_addr = new InetAddress(); 31 | Socket *clnt_sock = new Socket(sock->accept(clnt_addr)); 32 | printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->getFd(), clnt_addr->getIp(), clnt_addr->getPort()); 33 | clnt_sock->setnonblocking(); //新接受到的连接设置为非阻塞式 34 | newConnectionCallback(clnt_sock); 35 | delete clnt_addr; 36 | } 37 | 38 | void Acceptor::setNewConnectionCallback(std::function _cb){ 39 | newConnectionCallback = _cb; 40 | } -------------------------------------------------------------------------------- /code/day12/src/Acceptor.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | 10 | class EventLoop; 11 | class Socket; 12 | class Channel; 13 | class Acceptor 14 | { 15 | private: 16 | EventLoop *loop; 17 | Socket *sock; 18 | Channel *acceptChannel; 19 | std::function newConnectionCallback; 20 | public: 21 | Acceptor(EventLoop *_loop); 22 | ~Acceptor(); 23 | void acceptConnection(); 24 | void setNewConnectionCallback(std::function); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /code/day12/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Buffer.h" 8 | #include 9 | #include 10 | Buffer::Buffer() {} 11 | 12 | Buffer::~Buffer() {} 13 | 14 | void Buffer::append(const char* _str, int _size){ 15 | for(int i = 0; i < _size; ++i){ 16 | if(_str[i] == '\0') break; 17 | buf.push_back(_str[i]); 18 | } 19 | } 20 | 21 | ssize_t Buffer::size(){ 22 | return buf.size(); 23 | } 24 | 25 | const char* Buffer::c_str(){ 26 | return buf.c_str(); 27 | } 28 | 29 | void Buffer::clear(){ 30 | buf.clear(); 31 | } 32 | 33 | void Buffer::getline(){ 34 | buf.clear(); 35 | std::getline(std::cin, buf); 36 | } 37 | 38 | void Buffer::setBuf(const char* _buf){ 39 | buf.clear(); 40 | buf.append(_buf); 41 | } -------------------------------------------------------------------------------- /code/day12/src/Buffer.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | 10 | class Buffer 11 | { 12 | private: 13 | std::string buf; 14 | public: 15 | Buffer(); 16 | ~Buffer(); 17 | 18 | void append(const char* _str, int _size); 19 | ssize_t size(); 20 | const char* c_str(); 21 | void clear(); 22 | void getline(); 23 | void setBuf(const char*); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /code/day12/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "Channel.h" 8 | #include "EventLoop.h" 9 | #include "Socket.h" 10 | #include 11 | #include 12 | 13 | Channel::Channel(EventLoop *_loop, int _fd) 14 | : loop(_loop), fd(_fd), events(0), ready(0), inEpoll(false){} 15 | 16 | Channel::~Channel(){ 17 | if(fd != -1){ 18 | close(fd); 19 | fd = -1; 20 | } 21 | } 22 | 23 | void Channel::handleEvent(){ 24 | if(ready & (EPOLLIN | EPOLLPRI)){ 25 | readCallback(); 26 | } 27 | if(ready & (EPOLLOUT)){ 28 | writeCallback(); 29 | } 30 | 31 | } 32 | 33 | void Channel::enableRead(){ 34 | events |= EPOLLIN | EPOLLPRI; 35 | loop->updateChannel(this); 36 | } 37 | 38 | void Channel::useET(){ 39 | events |= EPOLLET; 40 | loop->updateChannel(this); 41 | } 42 | int Channel::getFd(){ 43 | return fd; 44 | } 45 | 46 | uint32_t Channel::getEvents(){ 47 | return events; 48 | } 49 | uint32_t Channel::getReady(){ 50 | return ready; 51 | } 52 | 53 | bool Channel::getInEpoll(){ 54 | return inEpoll; 55 | } 56 | 57 | void Channel::setInEpoll(bool _in){ 58 | inEpoll = _in; 59 | } 60 | 61 | void Channel::setReady(uint32_t _ev){ 62 | ready = _ev; 63 | } 64 | 65 | void Channel::setReadCallback(std::function _cb){ 66 | readCallback = _cb; 67 | } 68 | -------------------------------------------------------------------------------- /code/day12/src/Channel.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | class Socket; 10 | class EventLoop; 11 | class Channel 12 | { 13 | private: 14 | EventLoop *loop; 15 | int fd; 16 | uint32_t events; 17 | uint32_t ready; 18 | bool inEpoll; 19 | std::function readCallback; 20 | std::function writeCallback; 21 | public: 22 | Channel(EventLoop *_loop, int _fd); 23 | ~Channel(); 24 | 25 | void handleEvent(); 26 | void enableRead(); 27 | 28 | int getFd(); 29 | uint32_t getEvents(); 30 | uint32_t getReady(); 31 | bool getInEpoll(); 32 | void setInEpoll(bool _in = true); 33 | void useET(); 34 | 35 | void setReady(uint32_t); 36 | void setReadCallback(std::function); 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /code/day12/src/Connection.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | class EventLoop; 10 | class Socket; 11 | class Channel; 12 | class Buffer; 13 | class Connection 14 | { 15 | private: 16 | EventLoop *loop; 17 | Socket *sock; 18 | Channel *channel; 19 | std::function deleteConnectionCallback; 20 | Buffer *readBuffer; 21 | public: 22 | Connection(EventLoop *_loop, Socket *_sock); 23 | ~Connection(); 24 | 25 | void echo(int sockfd); 26 | void setDeleteConnectionCallback(std::function); 27 | void send(int sockfd); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /code/day12/src/Epoll.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | #include 10 | 11 | class Channel; 12 | class Epoll 13 | { 14 | private: 15 | int epfd; 16 | struct epoll_event *events; 17 | public: 18 | Epoll(); 19 | ~Epoll(); 20 | 21 | void updateChannel(Channel*); 22 | void deleteChannel(Channel*); 23 | 24 | std::vector poll(int timeout = -1); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /code/day12/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "EventLoop.h" 8 | #include "Epoll.h" 9 | #include "Channel.h" 10 | #include 11 | 12 | EventLoop::EventLoop() : ep(nullptr), quit(false){ 13 | ep = new Epoll(); 14 | } 15 | 16 | EventLoop::~EventLoop(){ 17 | delete ep; 18 | } 19 | 20 | 21 | void EventLoop::loop(){ 22 | while(!quit){ 23 | std::vector chs; 24 | chs = ep->poll(); 25 | for(auto it = chs.begin(); it != chs.end(); ++it){ 26 | (*it)->handleEvent(); 27 | } 28 | } 29 | } 30 | 31 | void EventLoop::updateChannel(Channel *ch){ 32 | ep->updateChannel(ch); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /code/day12/src/EventLoop.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | /****************************** 8 | * author: yuesong-feng 9 | * 10 | * 11 | * 12 | ******************************/ 13 | #pragma once 14 | #include 15 | 16 | class Epoll; 17 | class Channel; 18 | class EventLoop 19 | { 20 | private: 21 | Epoll *ep; 22 | bool quit; 23 | public: 24 | EventLoop(); 25 | ~EventLoop(); 26 | 27 | void loop(); 28 | void updateChannel(Channel*); 29 | 30 | void addThread(std::function); 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /code/day12/src/Server.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #pragma once 8 | #include 9 | #include 10 | class EventLoop; 11 | class Socket; 12 | class Acceptor; 13 | class Connection; 14 | class ThreadPool; 15 | class Server 16 | { 17 | private: 18 | EventLoop *mainReactor; 19 | Acceptor *acceptor; 20 | std::map connections; 21 | std::vector subReactors; 22 | ThreadPool *thpool; 23 | public: 24 | Server(EventLoop*); 25 | ~Server(); 26 | 27 | void handleReadEvent(int); 28 | void newConnection(Socket *sock); 29 | void deleteConnection(int sockfd); 30 | }; 31 | 32 | 33 | -------------------------------------------------------------------------------- /code/day12/src/Socket.h: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | 8 | #pragma once 9 | #include 10 | 11 | class InetAddress 12 | { 13 | private: 14 | struct sockaddr_in addr; 15 | public: 16 | InetAddress(); 17 | InetAddress(const char* _ip, uint16_t _port); 18 | ~InetAddress(); 19 | 20 | void setInetAddr(sockaddr_in _addr); 21 | sockaddr_in getAddr(); 22 | char* getIp(); 23 | uint16_t getPort(); 24 | }; 25 | 26 | class Socket 27 | { 28 | private: 29 | int fd; 30 | public: 31 | Socket(); 32 | Socket(int _fd); 33 | ~Socket(); 34 | 35 | void bind(InetAddress*); 36 | void listen(); 37 | int accept(InetAddress*); 38 | 39 | void connect(InetAddress*); 40 | 41 | void setnonblocking(); 42 | int getFd(); 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /code/day12/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | * author: yuesong-feng 3 | * 4 | * 5 | * 6 | ******************************/ 7 | #include "ThreadPool.h" 8 | 9 | ThreadPool::ThreadPool(int size) : stop(false){ 10 | for(int i = 0; i < size; ++i){ 11 | threads.emplace_back(std::thread([this](){ 12 | while(true){ 13 | std::function task; 14 | { 15 | std::unique_lock lock(tasks_mtx); 16 | cv.wait(lock, [this](){ 17 | return stop || !tasks.empty(); 18 | }); 19 | if(stop && tasks.empty()) return; 20 | task = tasks.front(); 21 | tasks.pop(); 22 | } 23 | task(); 24 | } 25 | })); 26 | } 27 | } 28 | 29 | ThreadPool::~ThreadPool(){ 30 | { 31 | std::unique_lock lock(tasks_mtx); 32 | stop = true; 33 | } 34 | cv.notify_all(); 35 | for(std::thread &th : threads){ 36 | if(th.joinable()) 37 | th.join(); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /code/day12/src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | 5 | void errif(bool condition, const char *errmsg){ 6 | if(condition){ 7 | perror(errmsg); 8 | exit(EXIT_FAILURE); 9 | } 10 | } -------------------------------------------------------------------------------- /code/day12/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | void errif(bool, const char*); 5 | 6 | #endif -------------------------------------------------------------------------------- /code/day13/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | DerivePointerAlignment: false 3 | PointerAlignment: Right 4 | ColumnLimit: 120 5 | 6 | # Default for clang-8, changed in later clangs. Set explicitly for forwards 7 | # compatibility with modern clangs 8 | IncludeBlocks: Preserve 9 | -------------------------------------------------------------------------------- /code/day13/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *__pycache__/ 3 | .vscode/settings.json -------------------------------------------------------------------------------- /code/day13/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/test/server", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${fileDirname}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": true 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /code/day13/build_support/clang_format_exclusions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuesong-feng/30dayMakeCppServer/5e3386d6d89b5d8c8898cf5283a6c92a43e373a9/code/day13/build_support/clang_format_exclusions.txt -------------------------------------------------------------------------------- /code/day13/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Acceptor.h" 12 | 13 | #include 14 | 15 | #include "Channel.h" 16 | 17 | #include "Socket.h" 18 | 19 | Acceptor::Acceptor(EventLoop *loop) : loop_(loop), sock_(nullptr), channel_(nullptr) { 20 | sock_ = new Socket(); 21 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 22 | sock_->Bind(addr); 23 | // sock->setnonblocking(); acceptor使用阻塞式IO比较好 24 | sock_->Listen(); 25 | channel_ = new Channel(loop_, sock_->GetFd()); 26 | std::function cb = std::bind(&Acceptor::AcceptConnection, this); 27 | channel_->SetReadCallback(cb); 28 | channel_->EnableRead(); 29 | delete addr; 30 | } 31 | 32 | Acceptor::~Acceptor() { 33 | delete channel_; 34 | delete sock_; 35 | } 36 | 37 | void Acceptor::AcceptConnection() { 38 | InetAddress *clnt_addr = new InetAddress(); 39 | Socket *clnt_sock = new Socket(sock_->Accept(clnt_addr)); 40 | printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->GetFd(), clnt_addr->GetIp(), clnt_addr->GetPort()); 41 | clnt_sock->SetNonBlocking(); // 新接受到的连接设置为非阻塞式 42 | new_connection_callback_(clnt_sock); 43 | delete clnt_addr; 44 | } 45 | 46 | void Acceptor::SetNewConnectionCallback(std::function const &callback) { 47 | new_connection_callback_ = callback; 48 | } 49 | -------------------------------------------------------------------------------- /code/day13/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Buffer.h" 12 | 13 | #include 14 | #include 15 | 16 | void Buffer::Append(const char *str, int size) { 17 | for (int i = 0; i < size; ++i) { 18 | if (str[i] == '\0') { 19 | break; 20 | } 21 | buf_.push_back(str[i]); 22 | } 23 | } 24 | 25 | ssize_t Buffer::Size() { return buf_.size(); } 26 | 27 | const char *Buffer::ToStr() { return buf_.c_str(); } 28 | 29 | void Buffer::Clear() { buf_.clear(); } 30 | 31 | void Buffer::Getline() { 32 | buf_.clear(); 33 | std::getline(std::cin, buf_); 34 | } 35 | 36 | void Buffer::SetBuf(const char *buf) { 37 | buf_.clear(); 38 | buf_.append(buf); 39 | } 40 | -------------------------------------------------------------------------------- /code/day13/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE pine_sources ${PROJECT_SOURCE_DIR}/src/*.cpp) 2 | add_library(pine_shared SHARED ${pine_sources}) 3 | -------------------------------------------------------------------------------- /code/day13/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Channel.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Channel.h" 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "EventLoop.h" 19 | #include "Socket.h" 20 | 21 | Channel::Channel(EventLoop *loop, int fd) 22 | : loop_(loop), fd_(fd), listen_events_(0), ready_events_(0), in_epoll_(false) {} 23 | 24 | Channel::~Channel() { 25 | if (fd_ != -1) { 26 | close(fd_); 27 | fd_ = -1; 28 | } 29 | } 30 | 31 | void Channel::HandleEvent() { 32 | if (ready_events_ & (EPOLLIN | EPOLLPRI)) { 33 | read_callback_(); 34 | } 35 | if (ready_events_ & (EPOLLOUT)) { 36 | write_callback_(); 37 | } 38 | } 39 | 40 | void Channel::EnableRead() { 41 | listen_events_ |= EPOLLIN | EPOLLPRI; 42 | loop_->UpdateChannel(this); 43 | } 44 | 45 | void Channel::UseET() { 46 | listen_events_ |= EPOLLET; 47 | loop_->UpdateChannel(this); 48 | } 49 | int Channel::GetFd() { return fd_; } 50 | 51 | uint32_t Channel::GetListenEvents() { return listen_events_; } 52 | uint32_t Channel::GetReadyEvents() { return ready_events_; } 53 | 54 | bool Channel::GetInEpoll() { return in_epoll_; } 55 | 56 | void Channel::SetInEpoll(bool in) { in_epoll_ = in; } 57 | 58 | void Channel::SetReadyEvents(uint32_t ev) { ready_events_ = ev; } 59 | 60 | void Channel::SetReadCallback(std::function const &callback) { read_callback_ = callback; } 61 | -------------------------------------------------------------------------------- /code/day13/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "EventLoop.h" 12 | 13 | #include 14 | 15 | #include "Channel.h" 16 | #include "Epoll.h" 17 | 18 | EventLoop::EventLoop() { epoll_ = new Epoll(); } 19 | 20 | EventLoop::~EventLoop() { delete epoll_; } 21 | 22 | void EventLoop::Loop() { 23 | while (!quit_) { 24 | std::vector chs; 25 | chs = epoll_->Poll(); 26 | for (auto &ch : chs) { 27 | ch->HandleEvent(); 28 | } 29 | } 30 | } 31 | 32 | void EventLoop::UpdateChannel(Channel *ch) { epoll_->UpdateChannel(ch); } 33 | -------------------------------------------------------------------------------- /code/day13/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ThreadPool.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "ThreadPool.h" 12 | 13 | ThreadPool::ThreadPool(unsigned int size) { 14 | for (unsigned int i = 0; i < size; ++i) { 15 | workers_.emplace_back(std::thread([this]() { 16 | while (true) { 17 | std::function task; 18 | { 19 | std::unique_lock lock(queue_mutex_); 20 | condition_variable_.wait(lock, [this]() { return stop_ || !tasks_.empty(); }); 21 | if (stop_ && tasks_.empty()) { 22 | return; 23 | } 24 | task = tasks_.front(); 25 | tasks_.pop(); 26 | } 27 | task(); 28 | } 29 | })); 30 | } 31 | } 32 | 33 | ThreadPool::~ThreadPool() { 34 | { 35 | std::unique_lock lock(queue_mutex_); 36 | stop_ = true; 37 | } 38 | condition_variable_.notify_all(); 39 | for (std::thread &th : workers_) { 40 | if (th.joinable()) { 41 | th.join(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /code/day13/src/include/Acceptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class EventLoop; 17 | class Socket; 18 | class Channel; 19 | class Acceptor { 20 | public: 21 | explicit Acceptor(EventLoop *loop); 22 | ~Acceptor(); 23 | 24 | DISALLOW_COPY_AND_MOVE(Acceptor); 25 | 26 | void AcceptConnection(); 27 | void SetNewConnectionCallback(std::function const &callback); 28 | 29 | private: 30 | EventLoop *loop_; 31 | Socket *sock_; 32 | Channel *channel_; 33 | std::function new_connection_callback_; 34 | }; 35 | -------------------------------------------------------------------------------- /code/day13/src/include/Buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include "Macros.h" 14 | 15 | class Buffer { 16 | public: 17 | Buffer() = default; 18 | ~Buffer() = default; 19 | 20 | DISALLOW_COPY_AND_MOVE(Buffer); 21 | 22 | void Append(const char *_str, int _size); 23 | ssize_t Size(); 24 | const char *ToStr(); 25 | void Clear(); 26 | void Getline(); 27 | void SetBuf(const char *buf); 28 | 29 | private: 30 | std::string buf_; 31 | }; 32 | -------------------------------------------------------------------------------- /code/day13/src/include/Channel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Channel.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class Socket; 17 | class EventLoop; 18 | class Channel { 19 | public: 20 | Channel(EventLoop *loop, int fd); 21 | ~Channel(); 22 | 23 | DISALLOW_COPY_AND_MOVE(Channel); 24 | 25 | void HandleEvent(); 26 | void EnableRead(); 27 | 28 | int GetFd(); 29 | uint32_t GetListenEvents(); 30 | uint32_t GetReadyEvents(); 31 | bool GetInEpoll(); 32 | void SetInEpoll(bool in = true); 33 | void UseET(); 34 | 35 | void SetReadyEvents(uint32_t ev); 36 | void SetReadCallback(std::function const &callback); 37 | 38 | private: 39 | EventLoop *loop_; 40 | int fd_; 41 | uint32_t listen_events_; 42 | uint32_t ready_events_; 43 | bool in_epoll_; 44 | std::function read_callback_; 45 | std::function write_callback_; 46 | }; 47 | -------------------------------------------------------------------------------- /code/day13/src/include/Connection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Connection.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class EventLoop; 17 | class Socket; 18 | class Channel; 19 | class Buffer; 20 | class Connection { 21 | public: 22 | Connection(EventLoop *loop, Socket *sock); 23 | ~Connection(); 24 | DISALLOW_COPY_AND_MOVE(Connection); 25 | 26 | void Echo(int sockfd); 27 | void SetDeleteConnectionCallback(std::function const &callback); 28 | void Send(int sockfd); 29 | 30 | private: 31 | EventLoop *loop_; 32 | Socket *sock_; 33 | Channel *channel_; 34 | std::function delete_connectioin_callback_; 35 | Buffer *read_buffer_; 36 | }; 37 | -------------------------------------------------------------------------------- /code/day13/src/include/Epoll.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Epoll.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | #ifdef OS_LINUX 17 | #include 18 | #endif 19 | 20 | class Channel; 21 | class Epoll { 22 | public: 23 | Epoll(); 24 | ~Epoll(); 25 | 26 | DISALLOW_COPY_AND_MOVE(Epoll); 27 | 28 | void UpdateChannel(Channel *ch); 29 | void DeleteChannel(Channel *ch); 30 | 31 | std::vector Poll(int timeout = -1); 32 | 33 | private: 34 | int epfd_{1}; 35 | struct epoll_event *events_{nullptr}; 36 | }; 37 | -------------------------------------------------------------------------------- /code/day13/src/include/EventLoop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class Epoll; 17 | class Channel; 18 | class EventLoop { 19 | public: 20 | EventLoop(); 21 | ~EventLoop(); 22 | 23 | DISALLOW_COPY_AND_MOVE(EventLoop); 24 | 25 | void Loop(); 26 | void UpdateChannel(Channel *ch); 27 | 28 | private: 29 | Epoll *epoll_{nullptr}; 30 | bool quit_{false}; 31 | }; 32 | -------------------------------------------------------------------------------- /code/day13/src/include/Macros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Macros.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #define OS_LINUX 13 | 14 | // Macros to disable copying and moving 15 | #define DISALLOW_COPY(cname) \ 16 | cname(const cname &) = delete; /* NOLINT */ \ 17 | cname &operator=(const cname &) = delete; /* NOLINT */ 18 | 19 | #define DISALLOW_MOVE(cname) \ 20 | cname(cname &&) = delete; /* NOLINT */ \ 21 | cname &operator=(cname &&) = delete; /* NOLINT */ 22 | 23 | #define DISALLOW_COPY_AND_MOVE(cname) \ 24 | DISALLOW_COPY(cname); \ 25 | DISALLOW_MOVE(cname); 26 | -------------------------------------------------------------------------------- /code/day13/src/include/Server.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Server.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | #include 16 | class EventLoop; 17 | class Socket; 18 | class Acceptor; 19 | class Connection; 20 | class ThreadPool; 21 | class Server { 22 | private: 23 | EventLoop *main_reactor_; 24 | Acceptor *acceptor_; 25 | std::map connections_; 26 | std::vector sub_reactors_; 27 | ThreadPool *thread_pool_; 28 | 29 | public: 30 | explicit Server(EventLoop *loop); 31 | ~Server(); 32 | 33 | DISALLOW_COPY_AND_MOVE(Server); 34 | 35 | void NewConnection(Socket *sock); 36 | void DeleteConnection(int sockfd); 37 | }; 38 | -------------------------------------------------------------------------------- /code/day13/src/include/Socket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Socket.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | 12 | #pragma once 13 | #include 14 | #include "Macros.h" 15 | 16 | class InetAddress { 17 | public: 18 | InetAddress(); 19 | InetAddress(const char *ip, uint16_t port); 20 | ~InetAddress() = default; 21 | 22 | DISALLOW_COPY_AND_MOVE(InetAddress); 23 | 24 | void SetAddr(sockaddr_in addr); 25 | sockaddr_in GetAddr(); 26 | const char *GetIp(); 27 | uint16_t GetPort(); 28 | 29 | private: 30 | struct sockaddr_in addr_ {}; 31 | }; 32 | 33 | class Socket { 34 | private: 35 | int fd_{-1}; 36 | 37 | public: 38 | Socket(); 39 | explicit Socket(int fd); 40 | ~Socket(); 41 | 42 | DISALLOW_COPY_AND_MOVE(Socket); 43 | 44 | void Bind(InetAddress *addr); 45 | void Listen(); 46 | int Accept(InetAddress *addr); 47 | 48 | void Connect(InetAddress *addr); 49 | 50 | void SetNonBlocking(); 51 | int GetFd(); 52 | }; 53 | -------------------------------------------------------------------------------- /code/day13/src/include/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | 13 | void ErrorIf(bool condition, const char *msg); 14 | -------------------------------------------------------------------------------- /code/day13/src/util.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "util.h" 12 | 13 | #include 14 | #include 15 | 16 | void ErrorIf(bool condition, const char *errmsg) { 17 | if (condition) { 18 | perror(errmsg); 19 | exit(EXIT_FAILURE); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /code/day13/test/server.cpp: -------------------------------------------------------------------------------- 1 | #include "Server.h" 2 | 3 | #include "EventLoop.h" 4 | 5 | int main() { 6 | EventLoop *loop = new EventLoop(); 7 | Server *server = new Server(loop); 8 | loop->Loop(); 9 | delete server; 10 | delete loop; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /code/day13/test/single_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "Buffer.h" 7 | #include "Socket.h" 8 | #include "util.h" 9 | 10 | int main() { 11 | Socket *sock = new Socket(); 12 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 13 | sock->Connect(addr); 14 | 15 | int sockfd = sock->GetFd(); 16 | 17 | Buffer *send_buffer = new Buffer(); 18 | Buffer *read_buffer = new Buffer(); 19 | 20 | while (true) { 21 | send_buffer->Getline(); 22 | ssize_t write_bytes = write(sockfd, send_buffer->ToStr(), send_buffer->Size()); 23 | if (write_bytes == -1) { 24 | printf("socket already disconnected, can't write any more!\n"); 25 | break; 26 | } 27 | int already_read = 0; 28 | char buf[1024]; // 这个buf大小无所谓 29 | while (true) { 30 | memset(&buf, 0, sizeof(buf)); 31 | ssize_t read_bytes = read(sockfd, buf, sizeof(buf)); 32 | if (read_bytes > 0) { 33 | read_buffer->Append(buf, read_bytes); 34 | already_read += read_bytes; 35 | } else if (read_bytes == 0) { // EOF 36 | printf("server disconnected!\n"); 37 | exit(EXIT_SUCCESS); 38 | } 39 | if (already_read >= send_buffer->Size()) { 40 | printf("message from server: %s\n", read_buffer->ToStr()); 41 | break; 42 | } 43 | } 44 | read_buffer->Clear(); 45 | } 46 | delete addr; 47 | delete sock; 48 | delete read_buffer; 49 | delete send_buffer; 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /code/day13/test/thread_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ThreadPool.h" 5 | 6 | void Print(int a, double b, const char *c, std::string const &d) { std::cout << a << b << c << d << std::endl; } 7 | 8 | void Test() { std::cout << "hellp" << std::endl; } 9 | 10 | int main(int argc, char const *argv[]) { 11 | ThreadPool *poll = new ThreadPool(); 12 | std::function func = std::bind(Print, 1, 3.14, "hello", std::string("world")); 13 | poll->Add(func); 14 | func = Test; 15 | poll->Add(func); 16 | delete poll; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /code/day14/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | DerivePointerAlignment: false 3 | PointerAlignment: Right 4 | ColumnLimit: 120 5 | 6 | # Default for clang-8, changed in later clangs. Set explicitly for forwards 7 | # compatibility with modern clangs 8 | IncludeBlocks: Preserve 9 | -------------------------------------------------------------------------------- /code/day14/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *__pycache__/ 3 | .vscode/settings.json -------------------------------------------------------------------------------- /code/day14/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb) Launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/build/bin/server", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${fileDirname}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": true 23 | } 24 | ] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /code/day14/build_support/clang_format_exclusions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuesong-feng/30dayMakeCppServer/5e3386d6d89b5d8c8898cf5283a6c92a43e373a9/code/day14/build_support/clang_format_exclusions.txt -------------------------------------------------------------------------------- /code/day14/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Acceptor.h" 12 | 13 | #include 14 | 15 | #include "Channel.h" 16 | 17 | #include "Socket.h" 18 | 19 | Acceptor::Acceptor(EventLoop *loop) : loop_(loop), sock_(nullptr), channel_(nullptr) { 20 | sock_ = new Socket(); 21 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 22 | sock_->Bind(addr); 23 | // sock->setnonblocking(); acceptor使用阻塞式IO比较好 24 | sock_->Listen(); 25 | channel_ = new Channel(loop_, sock_->GetFd()); 26 | std::function cb = std::bind(&Acceptor::AcceptConnection, this); 27 | channel_->SetReadCallback(cb); 28 | channel_->EnableRead(); 29 | delete addr; 30 | } 31 | 32 | Acceptor::~Acceptor() { 33 | delete channel_; 34 | delete sock_; 35 | } 36 | 37 | void Acceptor::AcceptConnection() { 38 | InetAddress *clnt_addr = new InetAddress(); 39 | Socket *clnt_sock = new Socket(sock_->Accept(clnt_addr)); 40 | printf("new client fd %d! IP: %s Port: %d\n", clnt_sock->GetFd(), clnt_addr->GetIp(), clnt_addr->GetPort()); 41 | clnt_sock->SetNonBlocking(); // 新接受到的连接设置为非阻塞式 42 | new_connection_callback_(clnt_sock); 43 | delete clnt_addr; 44 | } 45 | 46 | void Acceptor::SetNewConnectionCallback(std::function const &callback) { 47 | new_connection_callback_ = callback; 48 | } 49 | -------------------------------------------------------------------------------- /code/day14/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Buffer.h" 12 | 13 | #include 14 | #include 15 | 16 | void Buffer::Append(const char *str, int size) { 17 | for (int i = 0; i < size; ++i) { 18 | if (str[i] == '\0') { 19 | break; 20 | } 21 | buf_.push_back(str[i]); 22 | } 23 | } 24 | 25 | ssize_t Buffer::Size() { return buf_.size(); } 26 | 27 | const char *Buffer::ToStr() { return buf_.c_str(); } 28 | 29 | void Buffer::Clear() { buf_.clear(); } 30 | 31 | void Buffer::Getline() { 32 | buf_.clear(); 33 | std::getline(std::cin, buf_); 34 | } 35 | 36 | void Buffer::SetBuf(const char *buf) { 37 | buf_.clear(); 38 | buf_.append(buf); 39 | } 40 | -------------------------------------------------------------------------------- /code/day14/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE pine_sources ${PROJECT_SOURCE_DIR}/src/*.cpp) 2 | add_library(pine_shared SHARED ${pine_sources}) 3 | -------------------------------------------------------------------------------- /code/day14/src/Channel.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Channel.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Channel.h" 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "EventLoop.h" 19 | #include "Socket.h" 20 | 21 | Channel::Channel(EventLoop *loop, int fd) 22 | : loop_(loop), fd_(fd), listen_events_(0), ready_events_(0), in_epoll_(false) {} 23 | 24 | Channel::~Channel() { 25 | if (fd_ != -1) { 26 | close(fd_); 27 | fd_ = -1; 28 | } 29 | } 30 | 31 | void Channel::HandleEvent() { 32 | if (ready_events_ & (EPOLLIN | EPOLLPRI)) { 33 | read_callback_(); 34 | } 35 | if (ready_events_ & (EPOLLOUT)) { 36 | write_callback_(); 37 | } 38 | } 39 | 40 | void Channel::EnableRead() { 41 | listen_events_ |= EPOLLIN | EPOLLPRI; 42 | loop_->UpdateChannel(this); 43 | } 44 | 45 | void Channel::UseET() { 46 | listen_events_ |= EPOLLET; 47 | loop_->UpdateChannel(this); 48 | } 49 | int Channel::GetFd() { return fd_; } 50 | 51 | uint32_t Channel::GetListenEvents() { return listen_events_; } 52 | uint32_t Channel::GetReadyEvents() { return ready_events_; } 53 | 54 | bool Channel::GetInEpoll() { return in_epoll_; } 55 | 56 | void Channel::SetInEpoll(bool in) { in_epoll_ = in; } 57 | 58 | void Channel::SetReadyEvents(uint32_t ev) { ready_events_ = ev; } 59 | 60 | void Channel::SetReadCallback(std::function const &callback) { read_callback_ = callback; } 61 | -------------------------------------------------------------------------------- /code/day14/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "EventLoop.h" 12 | 13 | #include 14 | 15 | #include "Channel.h" 16 | #include "Epoll.h" 17 | 18 | EventLoop::EventLoop() { epoll_ = new Epoll(); } 19 | 20 | EventLoop::~EventLoop() { delete epoll_; } 21 | 22 | void EventLoop::Loop() { 23 | while (!quit_) { 24 | std::vector chs; 25 | chs = epoll_->Poll(); 26 | for (auto &ch : chs) { 27 | ch->HandleEvent(); 28 | } 29 | } 30 | } 31 | 32 | void EventLoop::UpdateChannel(Channel *ch) { epoll_->UpdateChannel(ch); } 33 | -------------------------------------------------------------------------------- /code/day14/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ThreadPool.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "ThreadPool.h" 12 | 13 | ThreadPool::ThreadPool(unsigned int size) { 14 | for (unsigned int i = 0; i < size; ++i) { 15 | workers_.emplace_back(std::thread([this]() { 16 | while (true) { 17 | std::function task; 18 | { 19 | std::unique_lock lock(queue_mutex_); 20 | condition_variable_.wait(lock, [this]() { return stop_ || !tasks_.empty(); }); 21 | if (stop_ && tasks_.empty()) { 22 | return; 23 | } 24 | task = tasks_.front(); 25 | tasks_.pop(); 26 | } 27 | task(); 28 | } 29 | })); 30 | } 31 | } 32 | 33 | ThreadPool::~ThreadPool() { 34 | { 35 | std::unique_lock lock(queue_mutex_); 36 | stop_ = true; 37 | } 38 | condition_variable_.notify_all(); 39 | for (std::thread &th : workers_) { 40 | if (th.joinable()) { 41 | th.join(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /code/day14/src/include/Acceptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class EventLoop; 17 | class Socket; 18 | class Channel; 19 | class Acceptor { 20 | public: 21 | explicit Acceptor(EventLoop *loop); 22 | ~Acceptor(); 23 | 24 | DISALLOW_COPY_AND_MOVE(Acceptor); 25 | 26 | void AcceptConnection(); 27 | void SetNewConnectionCallback(std::function const &callback); 28 | 29 | private: 30 | EventLoop *loop_; 31 | Socket *sock_; 32 | Channel *channel_; 33 | std::function new_connection_callback_; 34 | }; 35 | -------------------------------------------------------------------------------- /code/day14/src/include/Buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include "Macros.h" 14 | 15 | class Buffer { 16 | public: 17 | Buffer() = default; 18 | ~Buffer() = default; 19 | 20 | DISALLOW_COPY_AND_MOVE(Buffer); 21 | 22 | void Append(const char *_str, int _size); 23 | ssize_t Size(); 24 | const char *ToStr(); 25 | void Clear(); 26 | void Getline(); 27 | void SetBuf(const char *buf); 28 | 29 | private: 30 | std::string buf_; 31 | }; 32 | -------------------------------------------------------------------------------- /code/day14/src/include/Channel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Channel.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class Socket; 17 | class EventLoop; 18 | class Channel { 19 | public: 20 | Channel(EventLoop *loop, int fd); 21 | ~Channel(); 22 | 23 | DISALLOW_COPY_AND_MOVE(Channel); 24 | 25 | void HandleEvent(); 26 | void EnableRead(); 27 | 28 | int GetFd(); 29 | uint32_t GetListenEvents(); 30 | uint32_t GetReadyEvents(); 31 | bool GetInEpoll(); 32 | void SetInEpoll(bool in = true); 33 | void UseET(); 34 | 35 | void SetReadyEvents(uint32_t ev); 36 | void SetReadCallback(std::function const &callback); 37 | 38 | private: 39 | EventLoop *loop_; 40 | int fd_; 41 | uint32_t listen_events_; 42 | uint32_t ready_events_; 43 | bool in_epoll_; 44 | std::function read_callback_; 45 | std::function write_callback_; 46 | }; 47 | -------------------------------------------------------------------------------- /code/day14/src/include/Connection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Connection.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class EventLoop; 17 | class Socket; 18 | class Channel; 19 | class Buffer; 20 | class Connection { 21 | public: 22 | enum State { 23 | Invalid = 1, 24 | Handshaking, 25 | Connected, 26 | Closed, 27 | Failed, 28 | }; 29 | Connection(EventLoop *loop, Socket *sock); 30 | ~Connection(); 31 | DISALLOW_COPY_AND_MOVE(Connection); 32 | 33 | void Read(); 34 | void Write(); 35 | 36 | void SetDeleteConnectionCallback(std::function const &callback); 37 | void SetOnConnectCallback(std::function const &callback); 38 | State GetState(); 39 | void Close(); 40 | void SetSendBuffer(const char *str); 41 | Buffer *GetReadBuffer(); 42 | const char *ReadBuffer(); 43 | Buffer *GetSendBuffer(); 44 | const char *SendBuffer(); 45 | void GetlineSendBuffer(); 46 | Socket *GetSocket(); 47 | 48 | void OnConnect(std::function fn); 49 | 50 | private: 51 | EventLoop *loop_; 52 | Socket *sock_; 53 | Channel *channel_{nullptr}; 54 | State state_{State::Invalid}; 55 | Buffer *read_buffer_{nullptr}; 56 | Buffer *send_buffer_{nullptr}; 57 | std::function delete_connection_callback_; 58 | 59 | std::function on_connect_callback_; 60 | 61 | void ReadNonBlocking(); 62 | void WriteNonBlocking(); 63 | void ReadBlocking(); 64 | void WriteBlocking(); 65 | }; 66 | -------------------------------------------------------------------------------- /code/day14/src/include/Epoll.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Epoll.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | #ifdef OS_LINUX 17 | #include 18 | #endif 19 | 20 | class Channel; 21 | class Epoll { 22 | public: 23 | Epoll(); 24 | ~Epoll(); 25 | 26 | DISALLOW_COPY_AND_MOVE(Epoll); 27 | 28 | void UpdateChannel(Channel *ch); 29 | void DeleteChannel(Channel *ch); 30 | 31 | std::vector Poll(int timeout = -1); 32 | 33 | private: 34 | int epfd_{1}; 35 | struct epoll_event *events_{nullptr}; 36 | }; 37 | -------------------------------------------------------------------------------- /code/day14/src/include/EventLoop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class Epoll; 17 | class Channel; 18 | class EventLoop { 19 | public: 20 | EventLoop(); 21 | ~EventLoop(); 22 | 23 | DISALLOW_COPY_AND_MOVE(EventLoop); 24 | 25 | void Loop(); 26 | void UpdateChannel(Channel *ch); 27 | 28 | private: 29 | Epoll *epoll_{nullptr}; 30 | bool quit_{false}; 31 | }; 32 | -------------------------------------------------------------------------------- /code/day14/src/include/Macros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Macros.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #define OS_LINUX 15 | 16 | // Macros to disable copying and moving 17 | #define DISALLOW_COPY(cname) \ 18 | cname(const cname &) = delete; /* NOLINT */ \ 19 | cname &operator=(const cname &) = delete; /* NOLINT */ 20 | 21 | #define DISALLOW_MOVE(cname) \ 22 | cname(cname &&) = delete; /* NOLINT */ \ 23 | cname &operator=(cname &&) = delete; /* NOLINT */ 24 | 25 | #define DISALLOW_COPY_AND_MOVE(cname) \ 26 | DISALLOW_COPY(cname); \ 27 | DISALLOW_MOVE(cname); 28 | 29 | #define ASSERT(expr, message) assert((expr) && (message)) 30 | 31 | #define UNREACHABLE(message) throw std::logic_error(message) 32 | -------------------------------------------------------------------------------- /code/day14/src/include/Server.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Server.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | #include 16 | #include 17 | class EventLoop; 18 | class Socket; 19 | class Acceptor; 20 | class Connection; 21 | class ThreadPool; 22 | class Server { 23 | private: 24 | EventLoop *main_reactor_; 25 | Acceptor *acceptor_; 26 | std::map connections_; 27 | std::vector sub_reactors_; 28 | ThreadPool *thread_pool_; 29 | std::function on_connect_callback_; 30 | 31 | public: 32 | explicit Server(EventLoop *loop); 33 | ~Server(); 34 | 35 | DISALLOW_COPY_AND_MOVE(Server); 36 | 37 | void NewConnection(Socket *sock); 38 | void DeleteConnection(Socket *sock); 39 | void OnConnect(std::function fn); 40 | }; 41 | -------------------------------------------------------------------------------- /code/day14/src/include/Socket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Socket.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | 12 | #pragma once 13 | #include 14 | #include "Macros.h" 15 | 16 | class InetAddress { 17 | public: 18 | InetAddress(); 19 | InetAddress(const char *ip, uint16_t port); 20 | ~InetAddress() = default; 21 | 22 | DISALLOW_COPY_AND_MOVE(InetAddress); 23 | 24 | void SetAddr(sockaddr_in addr); 25 | sockaddr_in GetAddr(); 26 | const char *GetIp(); 27 | uint16_t GetPort(); 28 | 29 | private: 30 | struct sockaddr_in addr_ {}; 31 | }; 32 | 33 | class Socket { 34 | private: 35 | int fd_{-1}; 36 | 37 | public: 38 | Socket(); 39 | explicit Socket(int fd); 40 | ~Socket(); 41 | 42 | DISALLOW_COPY_AND_MOVE(Socket); 43 | 44 | void Bind(InetAddress *addr); 45 | void Listen(); 46 | int Accept(InetAddress *addr); 47 | 48 | void Connect(InetAddress *addr); 49 | void Connect(const char *ip, uint16_t port); 50 | 51 | void SetNonBlocking(); 52 | bool IsNonBlocking(); 53 | int GetFd(); 54 | }; 55 | -------------------------------------------------------------------------------- /code/day14/src/include/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | 13 | void ErrorIf(bool condition, const char *msg); 14 | -------------------------------------------------------------------------------- /code/day14/src/util.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "util.h" 12 | 13 | #include 14 | #include 15 | 16 | void ErrorIf(bool condition, const char *errmsg) { 17 | if (condition) { 18 | perror(errmsg); 19 | exit(EXIT_FAILURE); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /code/day14/test/multiple_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "Connection.h" 8 | #include "Socket.h" 9 | #include "ThreadPool.h" 10 | 11 | void OneClient(int msgs, int wait) { 12 | Socket *sock = new Socket(); 13 | sock->Connect("127.0.0.1", 1234); 14 | Connection *conn = new Connection(nullptr, sock); 15 | sleep(wait); 16 | int count = 0; 17 | while (count < msgs) { 18 | conn->SetSendBuffer("I'm client!"); 19 | conn->Write(); 20 | if (conn->GetState() == Connection::State::Closed) { 21 | conn->Close(); 22 | break; 23 | } 24 | conn->Read(); 25 | std::cout << "msg count " << count++ << ": " << conn->ReadBuffer() << std::endl; 26 | } 27 | delete conn; 28 | } 29 | 30 | int main(int argc, char *argv[]) { 31 | int threads = 100; 32 | int msgs = 100; 33 | int wait = 0; 34 | int o = -1; 35 | const char *optstring = "t:m:w:"; 36 | while ((o = getopt(argc, argv, optstring)) != -1) { 37 | switch (o) { 38 | case 't': 39 | threads = std::stoi(optarg); 40 | break; 41 | case 'm': 42 | msgs = std::stoi(optarg); 43 | break; 44 | case 'w': 45 | wait = std::stoi(optarg); 46 | break; 47 | case '?': 48 | printf("error optopt: %c\n", optopt); 49 | printf("error opterr: %d\n", opterr); 50 | break; 51 | default: 52 | break; 53 | } 54 | } 55 | 56 | ThreadPool *poll = new ThreadPool(threads); 57 | std::function func = std::bind(OneClient, msgs, wait); 58 | for (int i = 0; i < threads; ++i) { 59 | poll->Add(func); 60 | } 61 | delete poll; 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /code/day14/test/server.cpp: -------------------------------------------------------------------------------- 1 | #include "Server.h" 2 | #include 3 | #include "Buffer.h" 4 | #include "Connection.h" 5 | #include "EventLoop.h" 6 | #include "Socket.h" 7 | 8 | int main() { 9 | EventLoop *loop = new EventLoop(); 10 | Server *server = new Server(loop); 11 | server->OnConnect([](Connection *conn) { 12 | conn->Read(); 13 | if (conn->GetState() == Connection::State::Closed) { 14 | conn->Close(); 15 | return; 16 | } 17 | std::cout << "Message from client " << conn->GetSocket()->GetFd() << ": " << conn->ReadBuffer() << std::endl; 18 | conn->SetSendBuffer(conn->ReadBuffer()); 19 | conn->Write(); 20 | }); 21 | 22 | loop->Loop(); 23 | delete server; 24 | delete loop; 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /code/day14/test/single_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | Socket *sock = new Socket(); 7 | sock->Connect("127.0.0.1", 1234); 8 | 9 | Connection *conn = new Connection(nullptr, sock); 10 | 11 | while (true) { 12 | conn->GetlineSendBuffer(); 13 | conn->Write(); 14 | if (conn->GetState() == Connection::State::Closed) { 15 | conn->Close(); 16 | break; 17 | } 18 | conn->Read(); 19 | std::cout << "Message from server: " << conn->ReadBuffer() << std::endl; 20 | } 21 | 22 | delete conn; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /code/day14/test/thread_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ThreadPool.h" 5 | 6 | void Print(int a, double b, const char *c, std::string const &d) { std::cout << a << b << c << d << std::endl; } 7 | 8 | void Test() { std::cout << "hellp" << std::endl; } 9 | 10 | int main(int argc, char const *argv[]) { 11 | ThreadPool *poll = new ThreadPool(); 12 | std::function func = std::bind(Print, 1, 3.14, "hello", std::string("world")); 13 | poll->Add(func); 14 | func = Test; 15 | poll->Add(func); 16 | delete poll; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /code/day15/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | DerivePointerAlignment: false 3 | PointerAlignment: Right 4 | ColumnLimit: 120 5 | 6 | # Default for clang-8, changed in later clangs. Set explicitly for forwards 7 | # compatibility with modern clangs 8 | IncludeBlocks: Preserve 9 | -------------------------------------------------------------------------------- /code/day15/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *__pycache__/ 3 | .vscode/ 4 | .cache/ 5 | .DS_store -------------------------------------------------------------------------------- /code/day15/build_support/clang_format_exclusions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuesong-feng/30dayMakeCppServer/5e3386d6d89b5d8c8898cf5283a6c92a43e373a9/code/day15/build_support/clang_format_exclusions.txt -------------------------------------------------------------------------------- /code/day15/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Acceptor.h" 12 | 13 | #include 14 | 15 | #include "Channel.h" 16 | 17 | #include "Socket.h" 18 | 19 | Acceptor::Acceptor(EventLoop *loop) : loop_(loop), sock_(nullptr), channel_(nullptr) { 20 | sock_ = new Socket(); 21 | InetAddress *addr = new InetAddress("127.0.0.1", 1234); 22 | sock_->Bind(addr); 23 | // sock->setnonblocking(); acceptor使用阻塞式IO比较好 24 | sock_->Listen(); 25 | channel_ = new Channel(loop_, sock_); 26 | std::function cb = std::bind(&Acceptor::AcceptConnection, this); 27 | channel_->SetReadCallback(cb); 28 | channel_->EnableRead(); 29 | delete addr; 30 | } 31 | 32 | Acceptor::~Acceptor() { 33 | delete channel_; 34 | delete sock_; 35 | } 36 | 37 | void Acceptor::AcceptConnection() { 38 | InetAddress *clnt_addr = new InetAddress(); 39 | Socket *clnt_sock = new Socket(sock_->Accept(clnt_addr)); 40 | clnt_sock->SetNonBlocking(); // 新接受到的连接设置为非阻塞式 41 | if(new_connection_callback_){ 42 | new_connection_callback_(clnt_sock); 43 | } 44 | delete clnt_addr; 45 | } 46 | 47 | void Acceptor::SetNewConnectionCallback(std::function const &callback) { 48 | new_connection_callback_ = callback; 49 | } 50 | -------------------------------------------------------------------------------- /code/day15/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Buffer.h" 12 | 13 | #include 14 | #include 15 | 16 | void Buffer::Append(const char *str, int size) { 17 | for (int i = 0; i < size; ++i) { 18 | if (str[i] == '\0') { 19 | break; 20 | } 21 | buf_.push_back(str[i]); 22 | } 23 | } 24 | 25 | ssize_t Buffer::Size() { return buf_.size(); } 26 | 27 | const char *Buffer::ToStr() { return buf_.c_str(); } 28 | 29 | void Buffer::Clear() { buf_.clear(); } 30 | 31 | void Buffer::Getline() { 32 | buf_.clear(); 33 | std::getline(std::cin, buf_); 34 | } 35 | 36 | void Buffer::SetBuf(const char *buf) { 37 | buf_.clear(); 38 | buf_.append(buf); 39 | } 40 | -------------------------------------------------------------------------------- /code/day15/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE pine_sources ${PROJECT_SOURCE_DIR}/src/*.cpp) 2 | add_library(pine_shared SHARED ${pine_sources}) 3 | -------------------------------------------------------------------------------- /code/day15/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "EventLoop.h" 12 | 13 | #include 14 | 15 | #include "Channel.h" 16 | #include "Poller.h" 17 | 18 | EventLoop::EventLoop() { poller_ = new Poller(); } 19 | 20 | EventLoop::~EventLoop() { 21 | Quit(); 22 | delete poller_; 23 | } 24 | 25 | void EventLoop::Loop() { 26 | while (!quit_) { 27 | std::vector chs; 28 | chs = poller_->Poll(); 29 | for (auto &ch : chs) { 30 | ch->HandleEvent(); 31 | } 32 | } 33 | } 34 | void EventLoop::Quit() { quit_ = true; } 35 | 36 | void EventLoop::UpdateChannel(Channel *ch) { poller_->UpdateChannel(ch); } 37 | void EventLoop::DeleteChannel(Channel *ch) { poller_->DeleteChannel(ch); } 38 | -------------------------------------------------------------------------------- /code/day15/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ThreadPool.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "ThreadPool.h" 12 | 13 | ThreadPool::ThreadPool(unsigned int size) { 14 | for (unsigned int i = 0; i < size; ++i) { 15 | workers_.emplace_back(std::thread([this]() { 16 | while (true) { 17 | std::function task; 18 | { 19 | std::unique_lock lock(queue_mutex_); 20 | condition_variable_.wait(lock, [this]() { return stop_ || !tasks_.empty(); }); 21 | if (stop_ && tasks_.empty()) { 22 | return; 23 | } 24 | task = tasks_.front(); 25 | tasks_.pop(); 26 | } 27 | task(); 28 | } 29 | })); 30 | } 31 | } 32 | 33 | ThreadPool::~ThreadPool() { 34 | { 35 | std::unique_lock lock(queue_mutex_); 36 | stop_ = true; 37 | } 38 | condition_variable_.notify_all(); 39 | for (std::thread &th : workers_) { 40 | if (th.joinable()) { 41 | th.join(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /code/day15/src/include/Acceptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class EventLoop; 17 | class Socket; 18 | class Channel; 19 | class Acceptor { 20 | public: 21 | explicit Acceptor(EventLoop *loop); 22 | ~Acceptor(); 23 | 24 | DISALLOW_COPY_AND_MOVE(Acceptor); 25 | 26 | void AcceptConnection(); 27 | void SetNewConnectionCallback(std::function const &callback); 28 | 29 | private: 30 | EventLoop *loop_; 31 | Socket *sock_; 32 | Channel *channel_; 33 | std::function new_connection_callback_; 34 | }; 35 | -------------------------------------------------------------------------------- /code/day15/src/include/Buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include "Macros.h" 14 | 15 | class Buffer { 16 | public: 17 | Buffer() = default; 18 | ~Buffer() = default; 19 | 20 | DISALLOW_COPY_AND_MOVE(Buffer); 21 | 22 | void Append(const char *_str, int _size); 23 | ssize_t Size(); 24 | const char *ToStr(); 25 | void Clear(); 26 | void Getline(); 27 | void SetBuf(const char *buf); 28 | 29 | private: 30 | std::string buf_; 31 | }; 32 | -------------------------------------------------------------------------------- /code/day15/src/include/Channel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Channel.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class Socket; 17 | class EventLoop; 18 | class Channel { 19 | public: 20 | Channel(EventLoop *loop, Socket *socket); 21 | ~Channel(); 22 | 23 | DISALLOW_COPY_AND_MOVE(Channel); 24 | 25 | void HandleEvent(); 26 | void EnableRead(); 27 | void EnableWrite(); 28 | 29 | Socket *GetSocket(); 30 | int GetListenEvents(); 31 | int GetReadyEvents(); 32 | bool GetExist(); 33 | void SetExist(bool in = true); 34 | void UseET(); 35 | 36 | void SetReadyEvents(int ev); 37 | void SetReadCallback(std::function const &callback); 38 | void SetWriteCallback(std::function const &callback); 39 | 40 | static const int READ_EVENT; // NOLINT 41 | static const int WRITE_EVENT; // NOLINT 42 | static const int ET; // NOLINT 43 | 44 | private: 45 | EventLoop *loop_; 46 | Socket *socket_; 47 | int listen_events_{0}; 48 | int ready_events_{0}; 49 | bool exist_{false}; 50 | std::function read_callback_; 51 | std::function write_callback_; 52 | }; 53 | -------------------------------------------------------------------------------- /code/day15/src/include/EventLoop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | 16 | class Poller; 17 | class Channel; 18 | class EventLoop { 19 | public: 20 | EventLoop(); 21 | ~EventLoop(); 22 | 23 | DISALLOW_COPY_AND_MOVE(EventLoop); 24 | 25 | void Loop(); 26 | void UpdateChannel(Channel *ch); 27 | void DeleteChannel(Channel *ch); 28 | void Quit(); 29 | 30 | private: 31 | Poller *poller_{nullptr}; 32 | bool quit_{false}; 33 | }; 34 | -------------------------------------------------------------------------------- /code/day15/src/include/Exception.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Exception.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-07 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #include 15 | 16 | enum ExceptionType { 17 | INVALID = 0, 18 | INVALID_SOCKET = 1, 19 | }; 20 | 21 | class Exception : public std::runtime_error { 22 | public: 23 | explicit Exception(const std::string &message) : std::runtime_error(message), type_(ExceptionType::INVALID) { 24 | std::string exception_message = "Message :: " + message + "\n"; 25 | std::cerr << exception_message; 26 | } 27 | 28 | Exception(ExceptionType type, const std::string &message) : std::runtime_error(message), type_(type) { 29 | std::string exception_message = 30 | "Exception Type :: " + ExceptionTypeToString(type_) + "\nMessage :: " + message + "\n"; 31 | std::cerr << exception_message; 32 | } 33 | static std::string ExceptionTypeToString(ExceptionType type) { 34 | switch (type) { 35 | case ExceptionType::INVALID: 36 | return "Invalid"; 37 | case ExceptionType::INVALID_SOCKET: 38 | return "Invalid socket"; 39 | default: 40 | return "Unknoen"; 41 | } 42 | } 43 | 44 | private: 45 | ExceptionType type_; 46 | }; 47 | -------------------------------------------------------------------------------- /code/day15/src/include/Log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Log.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-07 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | class Log 13 | { 14 | private: 15 | /* data */ 16 | public: 17 | Log(/* args */); 18 | ~Log(); 19 | }; 20 | 21 | Log::Log(/* args */) 22 | { 23 | } 24 | 25 | Log::~Log() 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /code/day15/src/include/Macros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Macros.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | 15 | // Macros to disable copying and moving 16 | #define DISALLOW_COPY(cname) \ 17 | cname(const cname &) = delete; /* NOLINT */ \ 18 | cname &operator=(const cname &) = delete; /* NOLINT */ 19 | 20 | #define DISALLOW_MOVE(cname) \ 21 | cname(cname &&) = delete; /* NOLINT */ \ 22 | cname &operator=(cname &&) = delete; /* NOLINT */ 23 | 24 | #define DISALLOW_COPY_AND_MOVE(cname) \ 25 | DISALLOW_COPY(cname); \ 26 | DISALLOW_MOVE(cname); 27 | 28 | #define ASSERT(expr, message) assert((expr) && (message)) 29 | 30 | #define UNREACHABLE(message) throw std::logic_error(message) 31 | -------------------------------------------------------------------------------- /code/day15/src/include/Poller.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Poller.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include "Macros.h" 14 | 15 | #ifdef OS_LINUX 16 | #include 17 | #endif 18 | 19 | #ifdef OS_MACOS 20 | #include 21 | #endif 22 | 23 | class Channel; 24 | class Poller { 25 | public: 26 | Poller(); 27 | ~Poller(); 28 | 29 | DISALLOW_COPY_AND_MOVE(Poller); 30 | 31 | void UpdateChannel(Channel *ch); 32 | void DeleteChannel(Channel *ch); 33 | 34 | std::vector Poll(int timeout = -1); 35 | 36 | private: 37 | int fd_{1}; 38 | #ifdef OS_LINUX 39 | struct epoll_event *events_{nullptr}; 40 | #endif 41 | 42 | #ifdef OS_MACOS 43 | struct kevent *events_{nullptr}; 44 | #endif 45 | }; 46 | -------------------------------------------------------------------------------- /code/day15/src/include/Server.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Server.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "Macros.h" 13 | 14 | #include 15 | #include 16 | #include 17 | class EventLoop; 18 | class Socket; 19 | class Acceptor; 20 | class Connection; 21 | class ThreadPool; 22 | class Server { 23 | private: 24 | EventLoop *main_reactor_; 25 | Acceptor *acceptor_; 26 | std::map connections_; 27 | std::vector sub_reactors_; 28 | ThreadPool *thread_pool_; 29 | std::function on_connect_callback_; 30 | std::function on_message_callback_; 31 | std::function new_connect_callback_; 32 | 33 | public: 34 | explicit Server(EventLoop *loop); 35 | ~Server(); 36 | 37 | DISALLOW_COPY_AND_MOVE(Server); 38 | 39 | void NewConnection(Socket *sock); 40 | void DeleteConnection(Socket *sock); 41 | void OnConnect(std::function fn); 42 | void OnMessage(std::function fn); 43 | void NewConnect(std::function fn); 44 | }; 45 | -------------------------------------------------------------------------------- /code/day15/src/include/SignalHandler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Signal.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-07 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #include 15 | 16 | std::map> handlers_; 17 | void signal_handler(int sig) { 18 | handlers_[sig](); 19 | } 20 | 21 | struct Signal { 22 | static void signal(int sig, const std::function &handler) { 23 | handlers_[sig] = handler; 24 | ::signal(sig, signal_handler); 25 | } 26 | }; -------------------------------------------------------------------------------- /code/day15/src/include/Socket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Socket.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | 12 | #pragma once 13 | #include 14 | #include "Macros.h" 15 | 16 | class InetAddress { 17 | public: 18 | InetAddress(); 19 | InetAddress(const char *ip, uint16_t port); 20 | ~InetAddress() = default; 21 | 22 | DISALLOW_COPY_AND_MOVE(InetAddress); 23 | 24 | void SetAddr(sockaddr_in addr); 25 | sockaddr_in GetAddr(); 26 | const char *GetIp(); 27 | uint16_t GetPort(); 28 | 29 | private: 30 | struct sockaddr_in addr_ {}; 31 | }; 32 | 33 | class Socket { 34 | private: 35 | int fd_{-1}; 36 | 37 | public: 38 | Socket(); 39 | explicit Socket(int fd); 40 | ~Socket(); 41 | 42 | DISALLOW_COPY_AND_MOVE(Socket); 43 | 44 | void Bind(InetAddress *addr); 45 | void Listen(); 46 | int Accept(InetAddress *addr); 47 | 48 | void Connect(InetAddress *addr); 49 | void Connect(const char *ip, uint16_t port); 50 | 51 | void SetNonBlocking(); 52 | bool IsNonBlocking(); 53 | int GetFd(); 54 | }; 55 | -------------------------------------------------------------------------------- /code/day15/src/include/pine.h: -------------------------------------------------------------------------------- 1 | #include "Server.h" 2 | #include "Buffer.h" 3 | #include "Connection.h" 4 | #include "EventLoop.h" 5 | #include "Socket.h" 6 | #include "SignalHandler.h" -------------------------------------------------------------------------------- /code/day15/src/include/util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | 13 | void ErrorIf(bool condition, const char *msg); 14 | -------------------------------------------------------------------------------- /code/day15/src/util.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file util.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "util.h" 12 | 13 | #include 14 | #include 15 | 16 | void ErrorIf(bool condition, const char *errmsg) { 17 | if (condition) { 18 | perror(errmsg); 19 | exit(EXIT_FAILURE); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /code/day15/test/chat_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | Socket *sock = new Socket(); 7 | sock->Connect("127.0.0.1", 1234); 8 | 9 | Connection *conn = new Connection(nullptr, sock); 10 | while(true){ 11 | conn->Read(); 12 | std::cout << "Message from server: " << conn->ReadBuffer() << std::endl; 13 | } 14 | // conn->Read(); 15 | 16 | // if (conn->GetState() == Connection::State::Connected) { 17 | // std::cout << conn->ReadBuffer() << std::endl; 18 | //} 19 | //conn->SetSendBuffer("Hello server!"); 20 | //conn->Write(); 21 | 22 | delete conn; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /code/day15/test/chat_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Connection.h" 4 | #include "EventLoop.h" 5 | #include "Server.h" 6 | #include "Socket.h" 7 | 8 | int main() { 9 | std::map clients; 10 | 11 | EventLoop *loop = new EventLoop(); 12 | Server *server = new Server(loop); 13 | 14 | server->NewConnect( 15 | [&](Connection *conn) { 16 | int clnt_fd = conn->GetSocket()->GetFd(); 17 | std::cout << "New connection fd: " << clnt_fd << std::endl; 18 | clients[clnt_fd] = conn; 19 | for(auto &each : clients){ 20 | Connection *client = each.second; 21 | client->Send(conn->ReadBuffer()); 22 | } 23 | }); 24 | 25 | server->OnMessage( 26 | [&](Connection *conn){ 27 | std::cout << "Message from client " << conn->ReadBuffer() << std::endl; 28 | for(auto &each : clients){ 29 | Connection *client = each.second; 30 | client->Send(conn->ReadBuffer()); 31 | } 32 | } 33 | ); 34 | 35 | loop->Loop(); 36 | return 0; 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /code/day15/test/echo_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | Socket *sock = new Socket(); 7 | sock->Connect("127.0.0.1", 1234); 8 | 9 | Connection *conn = new Connection(nullptr, sock); 10 | 11 | while (true) { 12 | conn->GetlineSendBuffer(); 13 | conn->Write(); 14 | if (conn->GetState() == Connection::State::Closed) { 15 | conn->Close(); 16 | break; 17 | } 18 | conn->Read(); 19 | std::cout << "Message from server: " << conn->ReadBuffer() << std::endl; 20 | } 21 | 22 | delete conn; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /code/day15/test/echo_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pine.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | 8 | Signal::signal(SIGINT, [&] { 9 | delete server; 10 | delete loop; 11 | std::cout << "\nServer exit!" << std::endl; 12 | exit(0); 13 | }); 14 | 15 | server->NewConnect( 16 | [](Connection *conn) { std::cout << "New connection fd: " << conn->GetSocket()->GetFd() << std::endl; }); 17 | 18 | server->OnMessage([](Connection *conn) { 19 | std::cout << "Message from client " << conn->ReadBuffer() << std::endl; 20 | if (conn->GetState() == Connection::State::Connected) { 21 | conn->Send(conn->ReadBuffer()); 22 | } 23 | }); 24 | 25 | loop->Loop(); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /code/day15/test/http_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pine.h" 3 | 4 | int main() { 5 | EventLoop *loop = new EventLoop(); 6 | Server *server = new Server(loop); 7 | 8 | Signal::signal(SIGINT, [&] { 9 | delete server; 10 | delete loop; 11 | std::cout << "\nServer exit!" << std::endl; 12 | exit(0); 13 | }); 14 | 15 | 16 | 17 | server->OnMessage([](Connection *conn) { 18 | std::cout << "Message from client " << conn->ReadBuffer() << std::endl; 19 | if (conn->GetState() == Connection::State::Connected) { 20 | conn->Send(conn->ReadBuffer()); 21 | } 22 | }); 23 | 24 | loop->Loop(); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /code/day16/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | DerivePointerAlignment: false 3 | PointerAlignment: Right 4 | ColumnLimit: 120 5 | 6 | # Default for clang-8, changed in later clangs. Set explicitly for forwards 7 | # compatibility with modern clangs 8 | IncludeBlocks: Preserve 9 | -------------------------------------------------------------------------------- /code/day16/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *__pycache__/ 3 | .vscode/ 4 | .cache/ 5 | .DS_store -------------------------------------------------------------------------------- /code/day16/build_support/clang_format_exclusions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuesong-feng/30dayMakeCppServer/5e3386d6d89b5d8c8898cf5283a6c92a43e373a9/code/day16/build_support/clang_format_exclusions.txt -------------------------------------------------------------------------------- /code/day16/src/Acceptor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Acceptor.h" 12 | 13 | #include 14 | #include 15 | #include "Channel.h" 16 | #include "Socket.h" 17 | 18 | Acceptor::Acceptor(EventLoop *loop) { 19 | socket_ = std::make_unique(); 20 | assert(socket_->Create() == RC_SUCCESS); 21 | assert(socket_->Bind("127.0.0.1", 1234) == RC_SUCCESS); 22 | assert(socket_->Listen() == RC_SUCCESS); 23 | 24 | channel_ = std::make_unique(socket_->fd(), loop); 25 | std::function cb = std::bind(&Acceptor::AcceptConnection, this); 26 | 27 | channel_->set_read_callback(cb); 28 | channel_->EnableRead(); 29 | } 30 | 31 | Acceptor::~Acceptor() {} 32 | 33 | RC Acceptor::AcceptConnection() const{ 34 | int clnt_fd = -1; 35 | if( socket_->Accept(clnt_fd) != RC_SUCCESS ) { 36 | return RC_ACCEPTOR_ERROR; 37 | } 38 | // TODO: remove 39 | fcntl(clnt_fd, F_SETFL, fcntl(clnt_fd, F_GETFL) | O_NONBLOCK); // 新接受到的连接设置为非阻塞式 40 | if (new_connection_callback_) { 41 | new_connection_callback_(clnt_fd); 42 | } 43 | return RC_SUCCESS; 44 | } 45 | 46 | void Acceptor::set_new_connection_callback(std::function const &callback) { 47 | new_connection_callback_ = std::move(callback); 48 | } 49 | -------------------------------------------------------------------------------- /code/day16/src/Buffer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "Buffer.h" 12 | 13 | const std::string &Buffer::buf() const { return buf_; } 14 | 15 | const char *Buffer::c_str() const { return buf_.c_str(); } 16 | 17 | void Buffer::set_buf(const char *buf) { 18 | std::string new_buf(buf); 19 | buf_.swap(new_buf); 20 | } 21 | 22 | size_t Buffer::Size() const { return buf_.size(); } 23 | 24 | void Buffer::Append(const char *str, int size) { 25 | for (int i = 0; i < size; ++i) { 26 | if (str[i] == '\0') { 27 | break; 28 | } 29 | buf_.push_back(str[i]); 30 | } 31 | } 32 | 33 | void Buffer::Clear() { buf_.clear(); } 34 | -------------------------------------------------------------------------------- /code/day16/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE pine_src ${PROJECT_SOURCE_DIR}/src/*.cpp) 2 | add_library(pine_shared SHARED ${pine_src}) 3 | -------------------------------------------------------------------------------- /code/day16/src/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "EventLoop.h" 12 | #include 13 | #include "Channel.h" 14 | #include "Poller.h" 15 | 16 | EventLoop::EventLoop() { poller_ = std::make_unique(); } 17 | 18 | EventLoop::~EventLoop() {} 19 | 20 | void EventLoop::Loop() const { 21 | while (true) { 22 | for (Channel *active_ch : poller_->Poll()) { 23 | active_ch->HandleEvent(); 24 | } 25 | } 26 | } 27 | 28 | void EventLoop::UpdateChannel(Channel *ch) const { poller_->UpdateChannel(ch); } 29 | 30 | void EventLoop::DeleteChannel(Channel *ch) const { poller_->DeleteChannel(ch); } 31 | -------------------------------------------------------------------------------- /code/day16/src/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ThreadPool.cpp 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #include "ThreadPool.h" 12 | 13 | ThreadPool::ThreadPool(unsigned int size) { 14 | for (unsigned int i = 0; i < size; ++i) { 15 | workers_.emplace_back(std::thread([this]() { 16 | while (true) { 17 | std::function task; 18 | { 19 | std::unique_lock lock(queue_mutex_); 20 | condition_variable_.wait(lock, [this]() { return stop_ || !tasks_.empty(); }); 21 | if (stop_ && tasks_.empty()) { 22 | return; 23 | } 24 | task = tasks_.front(); 25 | tasks_.pop(); 26 | } 27 | task(); 28 | } 29 | })); 30 | } 31 | } 32 | 33 | ThreadPool::~ThreadPool() { 34 | { 35 | std::unique_lock lock(queue_mutex_); 36 | stop_ = true; 37 | } 38 | condition_variable_.notify_all(); 39 | for (std::thread &th : workers_) { 40 | if (th.joinable()) { 41 | th.join(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /code/day16/src/include/Acceptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Acceptor.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "common.h" 13 | #include 14 | #include 15 | 16 | class Acceptor { 17 | public: 18 | DISALLOW_COPY_AND_MOVE(Acceptor); 19 | explicit Acceptor(EventLoop *loop); 20 | ~Acceptor(); 21 | 22 | RC AcceptConnection() const; 23 | void set_new_connection_callback(std::function const &callback); 24 | 25 | private: 26 | std::unique_ptr socket_; 27 | std::unique_ptr channel_; 28 | std::function new_connection_callback_; 29 | }; 30 | -------------------------------------------------------------------------------- /code/day16/src/include/Buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Buffer.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #include "common.h" 15 | 16 | class Buffer { 17 | public: 18 | DISALLOW_COPY_AND_MOVE(Buffer); 19 | Buffer() = default; 20 | ~Buffer() = default; 21 | 22 | const std::string &buf() const; 23 | const char* c_str() const; 24 | void set_buf(const char *buf); 25 | 26 | size_t Size() const; 27 | void Append(const char *_str, int _size); 28 | void Clear(); 29 | 30 | private: 31 | std::string buf_; 32 | }; 33 | -------------------------------------------------------------------------------- /code/day16/src/include/Channel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Channel.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include "common.h" 14 | 15 | class Channel { 16 | public: 17 | DISALLOW_COPY_AND_MOVE(Channel); 18 | Channel(int fd, EventLoop *loop); 19 | ~Channel(); 20 | 21 | 22 | void HandleEvent() const; 23 | void EnableRead(); 24 | void EnableWrite(); 25 | 26 | int fd() const; 27 | short listen_events() const; 28 | short ready_events() const; 29 | bool exist() const; 30 | void set_exist(bool in = true); 31 | void EnableET(); 32 | 33 | void set_ready_event(short ev); 34 | void set_read_callback(std::function const &callback); 35 | void set_write_callback(std::function const &callback); 36 | 37 | static const short READ_EVENT; 38 | static const short WRITE_EVENT; 39 | static const short ET; 40 | 41 | private: 42 | int fd_; 43 | EventLoop *loop_; 44 | short listen_events_; 45 | short ready_events_; 46 | bool exist_; 47 | std::function read_callback_; 48 | std::function write_callback_; 49 | }; 50 | -------------------------------------------------------------------------------- /code/day16/src/include/Connection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Connection.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include "common.h" 14 | 15 | class Connection { 16 | public: 17 | enum State { 18 | Invalid = 0, 19 | Connecting, 20 | Connected, 21 | Closed, 22 | }; 23 | DISALLOW_COPY_AND_MOVE(Connection); 24 | Connection(int fd, EventLoop *loop); 25 | ~Connection(); 26 | 27 | void set_delete_connection(std::function const &fn); 28 | void set_on_connect(std::function const &fn); 29 | void set_on_recv(std::function const &fn); 30 | State state() const; 31 | Socket *socket() const; 32 | void set_send_buf(const char *str); 33 | Buffer *read_buf(); 34 | Buffer *send_buf(); 35 | 36 | RC Read(); 37 | RC Write(); 38 | RC Send(std::string msg); 39 | 40 | void Close(); 41 | 42 | void onConnect(std::function fn); 43 | void onMessage(std::function fn); 44 | 45 | private: 46 | void Business(); 47 | RC ReadNonBlocking(); 48 | RC WriteNonBlocking(); 49 | RC ReadBlocking(); 50 | RC WriteBlocking(); 51 | 52 | private: 53 | std::unique_ptr socket_; 54 | std::unique_ptr channel_; 55 | 56 | State state_; 57 | std::unique_ptr read_buf_; 58 | std::unique_ptr send_buf_; 59 | 60 | std::function delete_connection_; 61 | std::function on_recv_; 62 | }; 63 | -------------------------------------------------------------------------------- /code/day16/src/include/EventLoop.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file EventLoop.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "common.h" 13 | #include 14 | 15 | class EventLoop { 16 | public: 17 | DISALLOW_COPY_AND_MOVE(EventLoop); 18 | EventLoop(); 19 | ~EventLoop(); 20 | 21 | 22 | void Loop() const; 23 | void UpdateChannel(Channel *ch) const; 24 | void DeleteChannel(Channel *ch) const; 25 | 26 | private: 27 | std::unique_ptr poller_; 28 | }; 29 | -------------------------------------------------------------------------------- /code/day16/src/include/Exception.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Exception.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-07 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #include 15 | 16 | enum ExceptionType { 17 | INVALID = 0, 18 | INVALID_SOCKET = 1, 19 | }; 20 | 21 | class Exception : public std::runtime_error { 22 | public: 23 | explicit Exception(const std::string &message) : std::runtime_error(message), type_(ExceptionType::INVALID) { 24 | std::string exception_message = "Message :: " + message + "\n"; 25 | std::cerr << exception_message; 26 | } 27 | 28 | Exception(ExceptionType type, const std::string &message) : std::runtime_error(message), type_(type) { 29 | std::string exception_message = 30 | "Exception Type :: " + ExceptionTypeToString(type_) + "\nMessage :: " + message + "\n"; 31 | std::cerr << exception_message; 32 | } 33 | static std::string ExceptionTypeToString(ExceptionType type) { 34 | switch (type) { 35 | case ExceptionType::INVALID: 36 | return "Invalid"; 37 | case ExceptionType::INVALID_SOCKET: 38 | return "Invalid socket"; 39 | default: 40 | return "Unknoen"; 41 | } 42 | } 43 | 44 | private: 45 | ExceptionType type_; 46 | }; 47 | -------------------------------------------------------------------------------- /code/day16/src/include/Log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Log.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-07 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | class Log 13 | { 14 | private: 15 | /* data */ 16 | public: 17 | Log(/* args */); 18 | ~Log(); 19 | }; 20 | 21 | Log::Log(/* args */) 22 | { 23 | } 24 | 25 | Log::~Log() 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /code/day16/src/include/Poller.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Poller.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "common.h" 13 | #include 14 | 15 | #ifdef OS_LINUX 16 | #include 17 | #endif 18 | 19 | #ifdef OS_MACOS 20 | #include 21 | #endif 22 | 23 | class Poller { 24 | public: 25 | DISALLOW_COPY_AND_MOVE(Poller); 26 | Poller(); 27 | ~Poller(); 28 | 29 | RC UpdateChannel(Channel *ch) const; 30 | RC DeleteChannel(Channel *ch) const; 31 | 32 | std::vector Poll(long timeout = -1) const; 33 | 34 | private: 35 | int fd_; 36 | 37 | #ifdef OS_LINUX 38 | struct epoll_event *events_{nullptr}; 39 | #endif 40 | 41 | #ifdef OS_MACOS 42 | struct kevent *events_; 43 | #endif 44 | }; 45 | -------------------------------------------------------------------------------- /code/day16/src/include/SignalHandler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Signal.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-02-07 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #include 15 | 16 | std::map> handlers_; 17 | void signal_handler(int sig) { 18 | handlers_[sig](); 19 | } 20 | 21 | struct Signal { 22 | static void signal(int sig, const std::function &handler) { 23 | handlers_[sig] = handler; 24 | ::signal(sig, signal_handler); 25 | } 26 | }; -------------------------------------------------------------------------------- /code/day16/src/include/Socket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Socket.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | 12 | #pragma once 13 | #include 14 | #include "common.h" 15 | 16 | class Socket { 17 | public: 18 | DISALLOW_COPY_AND_MOVE(Socket); 19 | Socket(); 20 | ~Socket(); 21 | void set_fd(int fd); 22 | int fd() const; 23 | std::string get_addr() const; 24 | RC Create(); 25 | RC Bind(const char *ip, uint16_t port) const; 26 | RC Listen() const; 27 | RC Accept(int &clnt_fd) const; 28 | RC Connect(const char *ip, uint16_t port) const; 29 | RC SetNonBlocking() const; 30 | bool IsNonBlocking() const; 31 | size_t RecvBufSize() const; 32 | 33 | private: 34 | int fd_; 35 | }; 36 | -------------------------------------------------------------------------------- /code/day16/src/include/TcpServer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file TcpServer.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | #include "common.h" 13 | #include 14 | #include 15 | #include 16 | 17 | class TcpServer { 18 | public: 19 | DISALLOW_COPY_AND_MOVE(TcpServer); 20 | TcpServer(); 21 | ~TcpServer(); 22 | void Start(); 23 | 24 | RC NewConnection(int fd); 25 | RC DeleteConnection(int fd); 26 | 27 | void onConnect(std::function fn); 28 | void onRecv(std::function fn); 29 | 30 | private: 31 | std::unique_ptr main_reactor_; 32 | std::unique_ptr acceptor_; 33 | 34 | std::unordered_map> connections_; 35 | std::vector> sub_reactors_; 36 | 37 | std::unique_ptr thread_pool_; 38 | 39 | std::function on_connect_; 40 | std::function on_recv_; 41 | }; 42 | -------------------------------------------------------------------------------- /code/day16/src/include/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Macros.h 3 | * @author 冯岳松 (yuesong-feng@foxmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2022-01-04 7 | * 8 | * @copyright Copyright (冯岳松) 2022 9 | * 10 | */ 11 | #pragma once 12 | 13 | class TcpServer; 14 | class EventLoop; 15 | class Poller; 16 | class PollPoller; 17 | class Acceptor; 18 | class Connection; 19 | class Channel; 20 | class Socket; 21 | class Buffer; 22 | class ThreadPool; 23 | 24 | // Macros to disable copying and moving 25 | #define DISALLOW_COPY(cname) \ 26 | cname(const cname &) = delete; \ 27 | cname &operator=(const cname &) = delete; 28 | 29 | #define DISALLOW_MOVE(cname) \ 30 | cname(cname &&) = delete; \ 31 | cname &operator=(cname &&) = delete; 32 | 33 | #define DISALLOW_COPY_AND_MOVE(cname) \ 34 | DISALLOW_COPY(cname); \ 35 | DISALLOW_MOVE(cname); 36 | 37 | // #define ASSERT(expr, message) assert((expr) && (message)) 38 | 39 | // #define UNREACHABLE(message) throw std::logic_error(message) 40 | 41 | enum RC { 42 | RC_UNDEFINED, 43 | RC_SUCCESS, 44 | RC_SOCKET_ERROR, 45 | RC_POLLER_ERROR, 46 | RC_CONNECTION_ERROR, 47 | RC_ACCEPTOR_ERROR, 48 | RC_UNIMPLEMENTED 49 | }; -------------------------------------------------------------------------------- /code/day16/src/include/pine.h: -------------------------------------------------------------------------------- 1 | #include "TcpServer.h" 2 | #include "Buffer.h" 3 | #include "Connection.h" 4 | #include "EventLoop.h" 5 | #include "Socket.h" 6 | #include "SignalHandler.h" 7 | #include "ThreadPool.h" -------------------------------------------------------------------------------- /code/day16/test/chat_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | // Socket *sock = new Socket(); 7 | // sock->Connect("127.0.0.1", 1234); 8 | 9 | // Connection *conn = new Connection(nullptr, sock); 10 | // while(true){ 11 | // conn->Read(); 12 | // std::cout << "Message from server: " << conn->ReadBuffer() << std::endl; 13 | // } 14 | // // conn->Read(); 15 | 16 | // // if (conn->GetState() == Connection::State::Connected) { 17 | // // std::cout << conn->ReadBuffer() << std::endl; 18 | // //} 19 | // //conn->SetSendBuffer("Hello server!"); 20 | // //conn->Write(); 21 | 22 | // delete conn; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /code/day16/test/chat_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Connection.h" 4 | #include "EventLoop.h" 5 | #include "TcpServer.h" 6 | #include "Socket.h" 7 | 8 | int main() { 9 | // std::map clients; 10 | 11 | // EventLoop *loop = new EventLoop(); 12 | // Server *server = new Server(loop); 13 | 14 | // server->NewConnect( 15 | // [&](Connection *conn) { 16 | // int clnt_fd = conn->GetSocket()->fd(); 17 | // std::cout << "New connection fd: " << clnt_fd << std::endl; 18 | // clients[clnt_fd] = conn; 19 | // for(auto &each : clients){ 20 | // Connection *client = each.second; 21 | // client->Send(conn->ReadBuffer()); 22 | // } 23 | // }); 24 | 25 | // server->OnMessage( 26 | // [&](Connection *conn){ 27 | // std::cout << "Message from client " << conn->ReadBuffer() << std::endl; 28 | // for(auto &each : clients){ 29 | // Connection *client = each.second; 30 | // client->Send(conn->ReadBuffer()); 31 | // } 32 | // } 33 | // ); 34 | 35 | // loop->Loop(); 36 | return 0; 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /code/day16/test/echo_client.cpp: -------------------------------------------------------------------------------- 1 | #include "pine.h" 2 | #include 3 | 4 | int main() { 5 | Socket *sock = new Socket(); 6 | sock->Create(); 7 | sock->Connect("127.0.0.1", 1234); 8 | 9 | Connection *conn = new Connection(sock->fd(), nullptr); 10 | 11 | while (true) { 12 | std::string input; 13 | std::getline(std::cin, input); 14 | conn->set_send_buf(input.c_str()); 15 | conn->Write(); 16 | if (conn->state() == Connection::State::Closed) { 17 | conn->Close(); 18 | break; 19 | } 20 | conn->Read(); 21 | std::cout << "Message from server: " << conn->read_buf()->c_str() << std::endl; 22 | } 23 | 24 | delete conn; 25 | delete sock; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /code/day16/test/echo_clients.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "pine.h" 4 | 5 | void OneClient(int msgs, int wait) { 6 | Socket *sock = new Socket(); 7 | sock->Create(); 8 | sock->Connect("127.0.0.1", 1234); 9 | 10 | Connection *conn = new Connection(sock->fd(), nullptr); 11 | sleep(wait); 12 | 13 | int count = 0; 14 | while (count < msgs) { 15 | conn->set_send_buf("I'm client!"); 16 | conn->Write(); 17 | if (conn->state() == Connection::State::Closed) { 18 | conn->Close(); 19 | break; 20 | } 21 | conn->Read(); 22 | std::cout << "msg count " << count++ << ": " << conn->read_buf()->c_str() << std::endl; 23 | } 24 | delete sock; 25 | delete conn; 26 | } 27 | 28 | int main(int argc, char *argv[]) { 29 | int threads = 100; 30 | int msgs = 100; 31 | int wait = 0; 32 | int o = -1; 33 | const char *optstring = "t:m:w:"; 34 | while ((o = getopt(argc, argv, optstring)) != -1) { 35 | switch (o) { 36 | case 't': 37 | threads = std::stoi(optarg); 38 | break; 39 | case 'm': 40 | msgs = std::stoi(optarg); 41 | break; 42 | case 'w': 43 | wait = std::stoi(optarg); 44 | break; 45 | case '?': 46 | printf("error optopt: %c\n", optopt); 47 | printf("error opterr: %d\n", opterr); 48 | break; 49 | default: 50 | break; 51 | } 52 | } 53 | 54 | ThreadPool *poll = new ThreadPool(threads); 55 | std::function func = std::bind(OneClient, msgs, wait); 56 | for (int i = 0; i < threads; ++i) { 57 | poll->Add(func); 58 | } 59 | 60 | delete poll; 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /code/day16/test/echo_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pine.h" 3 | 4 | int main() { 5 | TcpServer *server = new TcpServer(); 6 | 7 | Signal::signal(SIGINT, [&] { 8 | delete server; 9 | std::cout << "\nServer exit!" << std::endl; 10 | exit(0); 11 | }); 12 | 13 | server->onConnect([](Connection *conn) { std::cout << "New connection fd: " << conn->socket()->fd() << std::endl; }); 14 | 15 | server->onRecv([](Connection *conn) { 16 | std::cout << "Message from client " << conn->read_buf()->c_str() << std::endl; 17 | conn->Send(conn->read_buf()->c_str()); 18 | }); 19 | 20 | server->Start(); 21 | 22 | delete server; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /code/day16/test/http_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pine.h" 3 | 4 | int main() { return 0; } 5 | --------------------------------------------------------------------------------