├── README.md ├── SUMMARY.md ├── TinyWebServer ├── .gitignore ├── CGImysql │ ├── README.md │ ├── sql_connection_pool.cpp │ └── sql_connection_pool.h ├── LICENSE ├── README.md ├── build.sh ├── config.cpp ├── config.h ├── http │ ├── README.md │ ├── http_conn.cpp │ └── http_conn.h ├── lock │ ├── README.md │ └── locker.h ├── log │ ├── README.md │ ├── block_queue.h │ ├── log.cpp │ └── log.h ├── main.cpp ├── makefile ├── root │ ├── .gitignore │ ├── README.md │ ├── fans.html │ ├── favicon.ico │ ├── frame.jpg │ ├── judge.html │ ├── log.html │ ├── logError.html │ ├── login.gif │ ├── loginnew.gif │ ├── picture.gif │ ├── picture.html │ ├── register.gif │ ├── register.html │ ├── registerError.html │ ├── registernew.gif │ ├── test1.jpg │ ├── video.gif │ ├── video.html │ ├── welcome.html │ ├── xxx.jpg │ └── xxx.mp4 ├── server ├── test_presure │ └── README.md ├── threadpool │ ├── README.md │ └── threadpool.h ├── timer │ ├── README.md │ ├── lst_timer.cpp │ └── lst_timer.h ├── webbench-1.5 │ ├── Makefile │ ├── debian │ │ ├── changelog │ │ ├── control │ │ ├── copyright │ │ ├── dirs │ │ └── rules │ ├── socket.c │ ├── tags │ ├── webbench │ ├── webbench-1.5.tar.gz │ ├── webbench.1 │ ├── webbench.c │ └── webbench.o ├── webserver.cpp └── webserver.h ├── WebServerCpp11 ├── .clang-format ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── WebBench │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── bin │ │ └── webbench │ ├── build.sh │ ├── debian │ │ ├── changelog │ │ ├── control │ │ ├── copyright │ │ ├── dirs │ │ └── rules │ ├── man │ │ └── man1 │ │ │ └── webbench.1 │ ├── share │ │ └── doc │ │ │ └── webbench │ │ │ ├── changelog │ │ │ └── copyright │ ├── socket.c │ ├── tags │ ├── test.sh │ ├── webbench │ ├── webbench.1 │ └── webbench.c ├── WebServer │ ├── CMakeLists.txt │ ├── Channel.cpp │ ├── Channel.h │ ├── Epoll.cpp │ ├── Epoll.h │ ├── EventLoop.cpp │ ├── EventLoop.h │ ├── EventLoopThread.cpp │ ├── EventLoopThread.h │ ├── EventLoopThreadPool.cpp │ ├── EventLoopThreadPool.h │ ├── HttpData.cpp │ ├── HttpData.h │ ├── Main.cpp │ ├── Makefile │ ├── Makefile.bak │ ├── Server.cpp │ ├── Server.h │ ├── ThreadPool.cpp │ ├── ThreadPool.h │ ├── Timer.cpp │ ├── Timer.h │ ├── Util.cpp │ ├── Util.h │ ├── base │ │ ├── AsyncLogging.cpp │ │ ├── AsyncLogging.h │ │ ├── CMakeLists.txt │ │ ├── Condition.h │ │ ├── CountDownLatch.cpp │ │ ├── CountDownLatch.h │ │ ├── CurrentThread.h │ │ ├── FileUtil.cpp │ │ ├── FileUtil.h │ │ ├── LogFile.cpp │ │ ├── LogFile.h │ │ ├── LogStream.cpp │ │ ├── LogStream.h │ │ ├── Logging.cpp │ │ ├── Logging.h │ │ ├── Log的设计.txt │ │ ├── MutexLock.h │ │ ├── Thread.cpp │ │ ├── Thread.h │ │ ├── noncopyable.h │ │ └── tests │ │ │ ├── CMakeLists.txt │ │ │ └── LoggingTest.cpp │ ├── config.h │ └── tests │ │ ├── CMakeLists.txt │ │ └── HTTPClient.cpp ├── build.sh ├── datum │ ├── WebServer.png │ ├── WebServerk.png │ ├── cloc.png │ ├── close.png │ ├── gdb.png │ ├── idle.png │ ├── keepalive.png │ ├── model.png │ ├── muduo.png │ └── muduok.png ├── old_version │ ├── old_version_0.1 │ │ ├── Makefile │ │ ├── Makefile1 │ │ ├── epoll.cpp │ │ ├── epoll.h │ │ ├── improvement.txt │ │ ├── index.html │ │ ├── main.cpp │ │ ├── requestData.cpp │ │ ├── requestData.h │ │ ├── threadpool.cpp │ │ ├── threadpool.h │ │ ├── util.cpp │ │ └── util.h │ ├── old_version_0.2 │ │ ├── Makefile │ │ ├── Makefile1 │ │ ├── epoll.cpp │ │ ├── epoll.h │ │ ├── favicon.ico │ │ ├── improvement.txt │ │ ├── index.html │ │ ├── main.cpp │ │ ├── requestData.cpp │ │ ├── requestData.h │ │ ├── threadpool.cpp │ │ ├── threadpool.h │ │ ├── util.cpp │ │ └── util.h │ ├── old_version_0.3 │ │ ├── Makefile │ │ ├── Makefile1 │ │ ├── config.h │ │ ├── epoll.cpp │ │ ├── epoll.h │ │ ├── favicon.ico │ │ ├── improvement.txt │ │ ├── index.html │ │ ├── main.cpp │ │ ├── requestData.cpp │ │ ├── requestData.h │ │ ├── threadpool.cpp │ │ ├── threadpool.h │ │ ├── util.cpp │ │ └── util.h │ ├── old_version_0.4 │ │ ├── Makefile │ │ ├── Makefile1 │ │ ├── base │ │ │ ├── mutexLock.hpp │ │ │ └── nocopyable.hpp │ │ ├── config.h │ │ ├── epoll.cpp │ │ ├── epoll.h │ │ ├── favicon.ico │ │ ├── improvement.txt │ │ ├── index.html │ │ ├── main.cpp │ │ ├── requestData.cpp │ │ ├── requestData.h │ │ ├── threadpool.cpp │ │ ├── threadpool.h │ │ ├── timer.cpp │ │ ├── timer.h │ │ ├── util.cpp │ │ └── util.h │ ├── old_version_0.5 │ │ ├── Makefile │ │ ├── Makefile1 │ │ ├── base │ │ │ ├── condition.hpp │ │ │ ├── mutexLock.hpp │ │ │ └── nocopyable.hpp │ │ ├── config.h │ │ ├── epoll.cpp │ │ ├── epoll.h │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.cpp │ │ ├── requestData.cpp │ │ ├── requestData.h │ │ ├── threadpool.cpp │ │ ├── threadpool.h │ │ ├── timer.cpp │ │ ├── timer.h │ │ ├── util.cpp │ │ └── util.h │ └── old_version_0.6 │ │ ├── AsyncLogging.cpp │ │ ├── AsyncLogging.h │ │ ├── Condition.h │ │ ├── CountDownLatch.cpp │ │ ├── CountDownLatch.h │ │ ├── CurrentThread.hpp │ │ ├── FileUtil.cpp │ │ ├── FileUtil.h │ │ ├── LogFile.cpp │ │ ├── LogFile.h │ │ ├── LogStream.cpp │ │ ├── LogStream.h │ │ ├── Logging.cpp │ │ ├── Logging.h │ │ ├── Makefile │ │ ├── Makefile1 │ │ ├── MutexLock.h │ │ ├── Thread.cpp │ │ ├── Thread.h │ │ ├── config.h │ │ ├── epoll.cpp │ │ ├── epoll.h │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.cpp │ │ ├── noncopyable.h │ │ ├── requestData.cpp │ │ ├── requestData.h │ │ ├── threadpool.cpp │ │ ├── threadpool.h │ │ ├── timer.cpp │ │ ├── timer.h │ │ ├── util.cpp │ │ └── util.h ├── 并发模型.md ├── 测试及改进.md ├── 版本历史.md ├── 连接的维护.md ├── 遇到的困难.md └── 项目目的.md └── YouShuang ├── README.md ├── ch05 ├── 5-01 byteorder.cpp ├── 5-03 testlisten.cpp ├── 5-05 testaccept.cpp ├── 5-06 oobsend.cpp ├── 5-07 oobrecv.cpp ├── 5-09 reuse_address.cpp ├── 5-10 set_send_buffer.cpp ├── 5-11 set_recv_buffer.cpp └── 5-12 access_daytime.cpp ├── ch06 ├── 6-01 testdup.cpp ├── 6-02 testwritev.cpp ├── 6-03 testsendfile.cpp ├── 6-04 testsplice.cpp └── 6-05 testtee.cpp ├── ch07 ├── 7-01 testeuid.cpp ├── 7-02 switchuser.cpp └── 7-03 daemonize.cpp ├── ch08 └── 8-03 httpparser.cpp ├── ch09 ├── 9-01 use_select.cpp ├── 9-03 mtlt.cpp ├── 9-04 oneshot.cpp ├── 9-05 unblockconnect.cpp ├── 9-06 mytalk_client.cpp ├── 9-07 mytalk_server.cpp ├── 9-08 multi_port.cpp └── 9-08 multi_port.cpp.bak ├── ch10 ├── 10-01 unievent.cpp └── 10-03 sigurg.cpp ├── ch11 ├── 11-01 connect_timeout.cpp ├── 11-02 lst_timer.h ├── 11-03 nonactive_conn.cpp ├── 11-04 io_timer.cpp ├── 11-05 tw_timer.h └── 11-06 time_heap.h ├── ch12 └── 12-01 libevent_test.c ├── ch13 ├── 13-03 sem.cpp ├── 13-04 shm_talk_server.cpp └── 13-05 passfd.cpp ├── ch14 ├── 14-01 mutual_lock.c ├── 14-02 locker.h ├── 14-03 thread_atfork.c └── 14-05 sigmask.c ├── ch15 ├── 15-01 processpool.h ├── 15-02 pool_cgi.cpp ├── 15-03 threadpool.h ├── 15-04 http_conn.h ├── 15-05 http_conn.cpp └── 15-06 main.cpp ├── ch16 └── 16-04 stress_client.cpp ├── rename.py └── springsnail ├── Makefile ├── config.xml ├── conn.cpp ├── conn.h ├── fdwrapper.cpp ├── fdwrapper.h ├── log.cpp ├── log.h ├── main.cpp ├── mgr.cpp ├── mgr.h └── processpool.h /README.md: -------------------------------------------------------------------------------- 1 | # 本书信息 2 | 3 | 《Linux 高性能服务器编程》和《Linux多线程服务端编程:使用muduo C++网络库》的笔记和源码,以及两个轻量级服务器的项目代码。 4 | 5 | GitHub:[https://github.com/Hansimov/linux-server](https://github.com/Hansimov/linux-server) 6 | 7 | ## 参考链接 8 | 9 | * raichen/LinuxServerCodes: Linux高性能服务器编程源码 10 | * [https://github.com/raichen/LinuxServerCodes](https://github.com/raichen/LinuxServerCodes) 11 | * chenshuo/muduo: Event-driven network library for multi-threaded Linux server in C++11 12 | * [https://github.com/chenshuo/muduo](https://github.com/chenshuo/muduo) 13 | 14 | 15 | 16 | * qinguoyi/TinyWebServer: Linux下C++轻量级Web服务器 17 | * [https://github.com/qinguoyi/TinyWebServer](https://github.com/qinguoyi/TinyWebServer) 18 | * linyacool/WebServer: A C++ High Performance Web Server 19 | * [https://github.com/linyacool/WebServer](https://github.com/linyacool/WebServer) 20 | 21 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [本书信息](README.md) 4 | 5 | -------------------------------------------------------------------------------- /TinyWebServer/.gitignore: -------------------------------------------------------------------------------- 1 | *ServerLog* -------------------------------------------------------------------------------- /TinyWebServer/CGImysql/README.md: -------------------------------------------------------------------------------- 1 | 2 | 校验 & 数据库连接池 3 | =============== 4 | 数据库连接池 5 | > * 单例模式,保证唯一 6 | > * list实现连接池 7 | > * 连接池为静态大小 8 | > * 互斥锁实现线程安全 9 | 10 | 校验 11 | > * HTTP请求采用POST方式 12 | > * 登录用户名和密码校验 13 | > * 用户注册及多线程注册安全 14 | -------------------------------------------------------------------------------- /TinyWebServer/CGImysql/sql_connection_pool.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONNECTION_POOL_ 2 | #define _CONNECTION_POOL_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../lock/locker.h" 12 | #include "../log/log.h" 13 | 14 | using namespace std; 15 | 16 | class connection_pool 17 | { 18 | public: 19 | MYSQL *GetConnection(); //获取数据库连接 20 | bool ReleaseConnection(MYSQL *conn); //释放连接 21 | int GetFreeConn(); //获取连接 22 | void DestroyPool(); //销毁所有连接 23 | 24 | //单例模式 25 | static connection_pool *GetInstance(); 26 | 27 | void init(string url, string User, string PassWord, string DataBaseName, int Port, int MaxConn, int close_log); 28 | 29 | private: 30 | connection_pool(); 31 | ~connection_pool(); 32 | 33 | int m_MaxConn; //最大连接数 34 | int m_CurConn; //当前已使用的连接数 35 | int m_FreeConn; //当前空闲的连接数 36 | locker lock; 37 | list connList; //连接池 38 | sem reserve; 39 | 40 | public: 41 | string m_url; //主机地址 42 | string m_Port; //数据库端口号 43 | string m_User; //登陆数据库用户名 44 | string m_PassWord; //登陆数据库密码 45 | string m_DatabaseName; //使用数据库名 46 | int m_close_log; //日志开关 47 | }; 48 | 49 | class connectionRAII{ 50 | 51 | public: 52 | connectionRAII(MYSQL **con, connection_pool *connPool); 53 | ~connectionRAII(); 54 | 55 | private: 56 | MYSQL *conRAII; 57 | connection_pool *poolRAII; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /TinyWebServer/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make server -------------------------------------------------------------------------------- /TinyWebServer/config.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | Config::Config(){ 4 | //端口号,默认9006 5 | PORT = 9006; 6 | 7 | //日志写入方式,默认同步 8 | LOGWrite = 0; 9 | 10 | //触发组合模式,默认listenfd LT + connfd LT 11 | TRIGMode = 0; 12 | 13 | //listenfd触发模式,默认LT 14 | LISTENTrigmode = 0; 15 | 16 | //connfd触发模式,默认LT 17 | CONNTrigmode = 0; 18 | 19 | //优雅关闭链接,默认不使用 20 | OPT_LINGER = 0; 21 | 22 | //数据库连接池数量,默认8 23 | sql_num = 8; 24 | 25 | //线程池内的线程数量,默认8 26 | thread_num = 8; 27 | 28 | //关闭日志,默认不关闭 29 | close_log = 0; 30 | 31 | //并发模型,默认是proactor 32 | actor_model = 0; 33 | } 34 | 35 | void Config::parse_arg(int argc, char*argv[]){ 36 | int opt; 37 | const char *str = "p:l:m:o:s:t:c:a:"; 38 | while ((opt = getopt(argc, argv, str)) != -1) 39 | { 40 | switch (opt) 41 | { 42 | case 'p': 43 | { 44 | PORT = atoi(optarg); 45 | break; 46 | } 47 | case 'l': 48 | { 49 | LOGWrite = atoi(optarg); 50 | break; 51 | } 52 | case 'm': 53 | { 54 | TRIGMode = atoi(optarg); 55 | break; 56 | } 57 | case 'o': 58 | { 59 | OPT_LINGER = atoi(optarg); 60 | break; 61 | } 62 | case 's': 63 | { 64 | sql_num = atoi(optarg); 65 | break; 66 | } 67 | case 't': 68 | { 69 | thread_num = atoi(optarg); 70 | break; 71 | } 72 | case 'c': 73 | { 74 | close_log = atoi(optarg); 75 | break; 76 | } 77 | case 'a': 78 | { 79 | actor_model = atoi(optarg); 80 | break; 81 | } 82 | default: 83 | break; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /TinyWebServer/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #include "webserver.h" 5 | 6 | using namespace std; 7 | 8 | class Config 9 | { 10 | public: 11 | Config(); 12 | ~Config(){}; 13 | 14 | void parse_arg(int argc, char*argv[]); 15 | 16 | //端口号 17 | int PORT; 18 | 19 | //日志写入方式 20 | int LOGWrite; 21 | 22 | //触发组合模式 23 | int TRIGMode; 24 | 25 | //listenfd触发模式 26 | int LISTENTrigmode; 27 | 28 | //connfd触发模式 29 | int CONNTrigmode; 30 | 31 | //优雅关闭链接 32 | int OPT_LINGER; 33 | 34 | //数据库连接池数量 35 | int sql_num; 36 | 37 | //线程池内的线程数量 38 | int thread_num; 39 | 40 | //是否关闭日志 41 | int close_log; 42 | 43 | //并发模型选择 44 | int actor_model; 45 | }; 46 | 47 | #endif -------------------------------------------------------------------------------- /TinyWebServer/http/README.md: -------------------------------------------------------------------------------- 1 | 2 | http连接处理类 3 | =============== 4 | 根据状态转移,通过主从状态机封装了http连接类。其中,主状态机在内部调用从状态机,从状态机将处理状态和数据传给主状态机 5 | > * 客户端发出http连接请求 6 | > * 从状态机读取数据,更新自身状态和接收数据,传给主状态机 7 | > * 主状态机根据从状态机状态,更新自身状态,决定响应请求还是继续读取 -------------------------------------------------------------------------------- /TinyWebServer/lock/README.md: -------------------------------------------------------------------------------- 1 | 2 | 线程同步机制包装类 3 | =============== 4 | 多线程同步,确保任一时刻只能有一个线程能进入关键代码段. 5 | > * 信号量 6 | > * 互斥锁 7 | > * 条件变量 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TinyWebServer/log/README.md: -------------------------------------------------------------------------------- 1 | 2 | 同步/异步日志系统 3 | =============== 4 | 同步/异步日志系统主要涉及了两个模块,一个是日志模块,一个是阻塞队列模块,其中加入阻塞队列模块主要是解决异步写入日志做准备. 5 | > * 自定义阻塞队列 6 | > * 单例模式创建日志 7 | > * 同步日志 8 | > * 异步日志 9 | > * 实现按天、超行分类 10 | -------------------------------------------------------------------------------- /TinyWebServer/log/log.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_H 2 | #define LOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "block_queue.h" 10 | 11 | using namespace std; 12 | 13 | class Log 14 | { 15 | public: 16 | //C++11以后,使用局部变量懒汉不用加锁 17 | static Log *get_instance() 18 | { 19 | static Log instance; 20 | return &instance; 21 | } 22 | 23 | static void *flush_log_thread(void *args) 24 | { 25 | Log::get_instance()->async_write_log(); 26 | } 27 | //可选择的参数有日志文件、日志缓冲区大小、最大行数以及最长日志条队列 28 | bool init(const char *file_name, int close_log, int log_buf_size = 8192, int split_lines = 5000000, int max_queue_size = 0); 29 | 30 | void write_log(int level, const char *format, ...); 31 | 32 | void flush(void); 33 | 34 | private: 35 | Log(); 36 | virtual ~Log(); 37 | void *async_write_log() 38 | { 39 | string single_log; 40 | //从阻塞队列中取出一个日志string,写入文件 41 | while (m_log_queue->pop(single_log)) 42 | { 43 | m_mutex.lock(); 44 | fputs(single_log.c_str(), m_fp); 45 | m_mutex.unlock(); 46 | } 47 | } 48 | 49 | private: 50 | char dir_name[128]; //路径名 51 | char log_name[128]; //log文件名 52 | int m_split_lines; //日志最大行数 53 | int m_log_buf_size; //日志缓冲区大小 54 | long long m_count; //日志行数记录 55 | int m_today; //因为按天分类,记录当前时间是那一天 56 | FILE *m_fp; //打开log的文件指针 57 | char *m_buf; 58 | block_queue *m_log_queue; //阻塞队列 59 | bool m_is_async; //是否同步标志位 60 | locker m_mutex; 61 | int m_close_log; //关闭日志 62 | }; 63 | 64 | #define LOG_DEBUG(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(0, format, ##__VA_ARGS__); Log::get_instance()->flush();} 65 | #define LOG_INFO(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(1, format, ##__VA_ARGS__); Log::get_instance()->flush();} 66 | #define LOG_WARN(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(2, format, ##__VA_ARGS__); Log::get_instance()->flush();} 67 | #define LOG_ERROR(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(3, format, ##__VA_ARGS__); Log::get_instance()->flush();} 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /TinyWebServer/main.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | //需要修改的数据库信息,登录名,密码,库名 6 | string user = "root"; 7 | string passwd = "q"; 8 | string databasename = "yourdb"; 9 | 10 | //命令行解析 11 | Config config; 12 | config.parse_arg(argc, argv); 13 | 14 | WebServer server; 15 | 16 | //初始化 17 | server.init(config.PORT, user, passwd, databasename, config.LOGWrite, 18 | config.OPT_LINGER, config.TRIGMode, config.sql_num, config.thread_num, 19 | config.close_log, config.actor_model); 20 | 21 | 22 | //日志 23 | server.log_write(); 24 | 25 | //数据库 26 | server.sql_pool(); 27 | 28 | //线程池 29 | server.thread_pool(); 30 | 31 | //触发模式 32 | server.trig_mode(); 33 | 34 | //监听 35 | server.eventListen(); 36 | 37 | //运行 38 | server.eventLoop(); 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /TinyWebServer/makefile: -------------------------------------------------------------------------------- 1 | CXX ?= g++ 2 | 3 | DEBUG ?= 1 4 | ifeq ($(DEBUG), 1) 5 | CXXFLAGS += -g 6 | else 7 | CXXFLAGS += -O2 8 | 9 | endif 10 | 11 | server: main.cpp ./timer/lst_timer.cpp ./http/http_conn.cpp ./log/log.cpp ./CGImysql/sql_connection_pool.cpp webserver.cpp config.cpp 12 | $(CXX) -o server $^ $(CXXFLAGS) -lpthread -lmysqlclient 13 | 14 | clean: 15 | rm -r server 16 | -------------------------------------------------------------------------------- /TinyWebServer/root/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/.gitignore -------------------------------------------------------------------------------- /TinyWebServer/root/README.md: -------------------------------------------------------------------------------- 1 | 界面跳转 2 | =============== 3 | 对html中action行为设置标志位,将method设置为POST 4 | > * 0 注册 5 | > * 1 登录 6 | > * 2 登录检测 7 | > * 3 注册检测 8 | > * 5 请求图片 9 | > * 6 请求视频 10 | > * 7 关注我 11 | -------------------------------------------------------------------------------- /TinyWebServer/root/fans.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | awsl 6 | 7 |
8 |
9 |
嘿嘿,你来啦,更多资料,请关注 “两猿社” 喔.
10 |
11 | 12 |
13 |
14 |
15 | 16 | -------------------------------------------------------------------------------- /TinyWebServer/root/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/favicon.ico -------------------------------------------------------------------------------- /TinyWebServer/root/frame.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/frame.jpg -------------------------------------------------------------------------------- /TinyWebServer/root/judge.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebServer 6 | 7 | 8 |
9 |
10 |
欢迎访问
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TinyWebServer/root/log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sign in 6 | 7 | 8 |
9 |
10 |
登录
11 |
12 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /TinyWebServer/root/logError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sign in 6 | 7 | 8 |
9 |
10 |
登录
11 |
12 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /TinyWebServer/root/login.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/login.gif -------------------------------------------------------------------------------- /TinyWebServer/root/loginnew.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/loginnew.gif -------------------------------------------------------------------------------- /TinyWebServer/root/picture.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/picture.gif -------------------------------------------------------------------------------- /TinyWebServer/root/picture.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | awsl 6 | 7 |
8 |
9 |
你居然想看图,不想关注我
10 |
11 | 12 |
13 |
14 |
15 | 16 | -------------------------------------------------------------------------------- /TinyWebServer/root/register.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/register.gif -------------------------------------------------------------------------------- /TinyWebServer/root/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sign up 6 | 7 | 8 |
9 |
10 |
注册
11 |
12 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /TinyWebServer/root/registerError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sign up 6 | 7 | 8 |
9 |
10 |
注册
11 |
12 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /TinyWebServer/root/registernew.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/registernew.gif -------------------------------------------------------------------------------- /TinyWebServer/root/test1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/test1.jpg -------------------------------------------------------------------------------- /TinyWebServer/root/video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/video.gif -------------------------------------------------------------------------------- /TinyWebServer/root/video.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | awsl 6 | 7 |
8 |
9 |
你居然想看视频,不想关注我
10 |
11 | 12 |
13 |
14 |
17 | 18 | -------------------------------------------------------------------------------- /TinyWebServer/root/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebServer 6 | 7 | 8 |
9 |
10 |
是时候做出选择了
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TinyWebServer/root/xxx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/xxx.jpg -------------------------------------------------------------------------------- /TinyWebServer/root/xxx.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/root/xxx.mp4 -------------------------------------------------------------------------------- /TinyWebServer/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/server -------------------------------------------------------------------------------- /TinyWebServer/test_presure/README.md: -------------------------------------------------------------------------------- 1 | 服务器压力测试 2 | =============== 3 | Webbench是有名的网站压力测试工具,它是由[Lionbridge](http://www.lionbridge.com)公司开发。 4 | 5 | > * 测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。 6 | > * 展示服务器的两项内容:每秒钟响应请求数和每秒钟传输数据量。 7 | 8 | 9 | 10 | 11 | 测试规则 12 | ------------ 13 | * 测试示例 14 | 15 | ```C++ 16 | webbench -c 500 -t 30 http://127.0.0.1/phpionfo.php 17 | ``` 18 | * 参数 19 | 20 | > * `-c` 表示客户端数 21 | > * `-t` 表示时间 22 | 23 | 24 | 测试结果 25 | --------- 26 | Webbench对服务器进行压力测试,经压力测试可以实现上万的并发连接. 27 | > * 并发连接总数:10500 28 | > * 访问服务器时间:5s 29 | > * 每秒钟响应请求数:552852 pages/min 30 | > * 每秒钟传输数据量:1031990 bytes/sec 31 | > * 所有访问均成功 32 | 33 |
34 | -------------------------------------------------------------------------------- /TinyWebServer/threadpool/README.md: -------------------------------------------------------------------------------- 1 | 2 | 半同步/半反应堆线程池 3 | =============== 4 | 使用一个工作队列完全解除了主线程和工作线程的耦合关系:主线程往工作队列中插入任务,工作线程通过竞争来取得任务并执行它。 5 | > * 同步I/O模拟proactor模式 6 | > * 半同步/半反应堆 7 | > * 线程池 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /TinyWebServer/timer/README.md: -------------------------------------------------------------------------------- 1 | 2 | 定时器处理非活动连接 3 | =============== 4 | 由于非活跃连接占用了连接资源,严重影响服务器的性能,通过实现一个服务器定时器,处理这种非活跃连接,释放连接资源。利用alarm函数周期性地触发SIGALRM信号,该信号的信号处理函数利用管道通知主循环执行定时器链表上的定时任务. 5 | > * 统一事件源 6 | > * 基于升序链表的定时器 7 | > * 处理非活动连接 8 | -------------------------------------------------------------------------------- /TinyWebServer/timer/lst_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef LST_TIMER 2 | #define LST_TIMER 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include "../log/log.h" 26 | 27 | class util_timer; 28 | 29 | struct client_data 30 | { 31 | sockaddr_in address; 32 | int sockfd; 33 | util_timer *timer; 34 | }; 35 | 36 | class util_timer 37 | { 38 | public: 39 | util_timer() : prev(NULL), next(NULL) {} 40 | 41 | public: 42 | time_t expire; 43 | 44 | void (* cb_func)(client_data *); 45 | client_data *user_data; 46 | util_timer *prev; 47 | util_timer *next; 48 | }; 49 | 50 | class sort_timer_lst 51 | { 52 | public: 53 | sort_timer_lst(); 54 | ~sort_timer_lst(); 55 | 56 | void add_timer(util_timer *timer); 57 | void adjust_timer(util_timer *timer); 58 | void del_timer(util_timer *timer); 59 | void tick(); 60 | 61 | private: 62 | void add_timer(util_timer *timer, util_timer *lst_head); 63 | 64 | util_timer *head; 65 | util_timer *tail; 66 | }; 67 | 68 | class Utils 69 | { 70 | public: 71 | Utils() {} 72 | ~Utils() {} 73 | 74 | void init(int timeslot); 75 | 76 | //对文件描述符设置非阻塞 77 | int setnonblocking(int fd); 78 | 79 | //将内核事件表注册读事件,ET模式,选择开启EPOLLONESHOT 80 | void addfd(int epollfd, int fd, bool one_shot, int TRIGMode); 81 | 82 | //信号处理函数 83 | static void sig_handler(int sig); 84 | 85 | //设置信号函数 86 | void addsig(int sig, void(handler)(int), bool restart = true); 87 | 88 | //定时处理任务,重新定时以不断触发SIGALRM信号 89 | void timer_handler(); 90 | 91 | void show_error(int connfd, const char *info); 92 | 93 | public: 94 | static int *u_pipefd; 95 | sort_timer_lst m_timer_lst; 96 | static int u_epollfd; 97 | int m_TIMESLOT; 98 | }; 99 | 100 | void cb_func(client_data *user_data); 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS?= -Wall -ggdb -W -O 2 | CC?= gcc 3 | LIBS?= 4 | LDFLAGS?= 5 | PREFIX?= /usr/local 6 | VERSION=1.5 7 | TMPDIR=/tmp/webbench-$(VERSION) 8 | 9 | all: webbench tags 10 | 11 | tags: *.c 12 | -ctags *.c 13 | 14 | install: webbench 15 | install -s webbench $(DESTDIR)$(PREFIX)/bin 16 | install -m 644 webbench.1 $(DESTDIR)$(PREFIX)/man/man1 17 | install -d $(DESTDIR)$(PREFIX)/share/doc/webbench 18 | install -m 644 debian/copyright $(DESTDIR)$(PREFIX)/share/doc/webbench 19 | install -m 644 debian/changelog $(DESTDIR)$(PREFIX)/share/doc/webbench 20 | 21 | webbench: webbench.o Makefile 22 | $(CC) $(CFLAGS) $(LDFLAGS) -o webbench webbench.o $(LIBS) 23 | 24 | clean: 25 | -rm -f *.o webbench *~ core *.core tags 26 | 27 | tar: clean 28 | -debian/rules clean 29 | rm -rf $(TMPDIR) 30 | install -d $(TMPDIR) 31 | cp -p Makefile webbench.c socket.c webbench.1 $(TMPDIR) 32 | install -d $(TMPDIR)/debian 33 | -cp -p debian/* $(TMPDIR)/debian 34 | ln -sf debian/copyright $(TMPDIR)/COPYRIGHT 35 | ln -sf debian/changelog $(TMPDIR)/ChangeLog 36 | -cd $(TMPDIR) && cd .. && tar cozf webbench-$(VERSION).tar.gz webbench-$(VERSION) 37 | 38 | webbench.o: webbench.c socket.c Makefile 39 | 40 | .PHONY: clean install all tar 41 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/debian/changelog: -------------------------------------------------------------------------------- 1 | webbench (1.5) unstable; urgency=low 2 | 3 | * allow building with both Gnu and BSD make 4 | 5 | -- Radim Kolar Fri, Jun 25 12:00:20 CEST 2004 6 | 7 | webbench (1.4) unstable; urgency=low 8 | 9 | * check if url is not too long 10 | * report correct program version number 11 | * use yield() when waiting for test start 12 | * corrected error codes 13 | * check availability of test server first 14 | * do not abort test if first request failed 15 | * report when some childrens are dead. 16 | * use alarm, not time() for lower syscal use by bench 17 | * use mode 644 for installed doc 18 | * makefile cleaned for better freebsd ports integration 19 | 20 | -- Radim Kolar Thu, 15 Jan 2004 11:15:52 +0100 21 | 22 | webbench (1.3) unstable; urgency=low 23 | 24 | * Build fixes for freeBSD 25 | * Default benchmark time 60 -> 30 26 | * generate tar with subdirectory 27 | * added to freeBSD ports collection 28 | 29 | -- Radim Kolar Mon, 12 Jan 2004 17:00:24 +0100 30 | 31 | webbench (1.2) unstable; urgency=low 32 | 33 | * Only debian-related bugfixes 34 | * Updated Debian/rules 35 | * Adapted to fit new directory system 36 | * moved from debstd to dh_* 37 | 38 | -- Radim Kolar Fri, 18 Jan 2002 12:33:04 +0100 39 | 40 | webbench (1.1) unstable; urgency=medium 41 | 42 | * Program debianized 43 | * added support for multiple methods (GET, HEAD, OPTIONS, TRACE) 44 | * added support for multiple HTTP versions (0.9 -- 1.1) 45 | * added long options 46 | * added multiple clients 47 | * wait for start of second before test 48 | * test time can be specified 49 | * better error checking when reading reply from server 50 | * FIX: tests was one second longer than expected 51 | 52 | -- Radim Kolar Thu, 16 Sep 1999 18:48:00 +0200 53 | 54 | Local variables: 55 | mode: debian-changelog 56 | End: 57 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/debian/control: -------------------------------------------------------------------------------- 1 | Source: webbench 2 | Section: web 3 | Priority: extra 4 | Maintainer: Radim Kolar 5 | Build-Depends: debhelper (>> 3.0.0) 6 | Standards-Version: 3.5.2 7 | 8 | Package: webbench 9 | Architecture: any 10 | Depends: ${shlibs:Depends} 11 | Description: Simple forking Web benchmark 12 | webbench is very simple program for benchmarking WWW or Proxy servers. 13 | Uses fork() for simulating multiple clients load. Can use HTTP 0.9 - 1.1 14 | requests, but Keep-Alive connections are not supported. 15 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/debian/copyright: -------------------------------------------------------------------------------- 1 | Webbench was written by Radim Kolar 1997-2004 (hsn@netmag.cz). 2 | 3 | UNIX sockets code (socket.c) taken from popclient 1.5 4/1/94 4 | public domain code, created by Virginia Tech Computing Center. 5 | 6 | Copyright: GPL (see /usr/share/common-licenses/GPL) 7 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/debian/dirs: -------------------------------------------------------------------------------- 1 | usr/bin -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # Sample debian/rules that uses debhelper. 3 | # GNU copyright 1997 to 1999 by Joey Hess. 4 | 5 | # Uncomment this to turn on verbose mode. 6 | #export DH_VERBOSE=1 7 | 8 | # This is the debhelper compatability version to use. 9 | export DH_COMPAT=3 10 | 11 | configure: configure-stamp 12 | configure-stamp: 13 | dh_testdir 14 | touch configure-stamp 15 | 16 | build: configure-stamp build-stamp 17 | build-stamp: 18 | dh_testdir 19 | $(MAKE) 20 | touch build-stamp 21 | 22 | clean: 23 | dh_testdir 24 | rm -f build-stamp configure-stamp 25 | 26 | # Add here commands to clean up after the build process. 27 | -$(MAKE) clean 28 | 29 | dh_clean 30 | 31 | install: build 32 | dh_testdir 33 | dh_testroot 34 | dh_clean -k 35 | dh_installdirs 36 | 37 | # Add here commands to install the package into debian/webbench. 38 | $(MAKE) install DESTDIR=$(CURDIR)/debian/webbench 39 | 40 | 41 | # Build architecture-independent files here. 42 | binary-indep: build install 43 | # We have nothing to do by default. 44 | 45 | # Build architecture-dependent files here. 46 | binary-arch: build install 47 | dh_testdir 48 | dh_testroot 49 | dh_installdocs 50 | dh_installman webbench.1 51 | dh_installchangelogs 52 | dh_link 53 | dh_strip 54 | dh_compress 55 | dh_fixperms 56 | # dh_makeshlibs 57 | dh_installdeb 58 | dh_shlibdeps 59 | dh_gencontrol 60 | dh_md5sums 61 | dh_builddeb 62 | 63 | binary: binary-indep binary-arch 64 | .PHONY: build clean binary-indep binary-arch binary install configure 65 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/socket.c: -------------------------------------------------------------------------------- 1 | /* $Id: socket.c 1.1 1995/01/01 07:11:14 cthuang Exp $ 2 | * 3 | * This module has been modified by Radim Kolar for OS/2 emx 4 | */ 5 | 6 | /*********************************************************************** 7 | module: socket.c 8 | program: popclient 9 | SCCS ID: @(#)socket.c 1.5 4/1/94 10 | programmer: Virginia Tech Computing Center 11 | compiler: DEC RISC C compiler (Ultrix 4.1) 12 | environment: DEC Ultrix 4.3 13 | description: UNIX sockets code. 14 | ***********************************************************************/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | int Socket(const char *host, int clientPort) 30 | { 31 | int sock; 32 | unsigned long inaddr; 33 | struct sockaddr_in ad; 34 | struct hostent *hp; 35 | 36 | memset(&ad, 0, sizeof(ad)); 37 | ad.sin_family = AF_INET; 38 | 39 | inaddr = inet_addr(host); 40 | if (inaddr != INADDR_NONE) 41 | memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr)); 42 | else 43 | { 44 | hp = gethostbyname(host); 45 | if (hp == NULL) 46 | return -1; 47 | memcpy(&ad.sin_addr, hp->h_addr, hp->h_length); 48 | } 49 | ad.sin_port = htons(clientPort); 50 | 51 | sock = socket(AF_INET, SOCK_STREAM, 0); 52 | if (sock < 0) 53 | return sock; 54 | if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0) 55 | return -1; 56 | return sock; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/tags: -------------------------------------------------------------------------------- 1 | !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ 2 | !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ 3 | !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ 4 | !_TAG_PROGRAM_NAME Exuberant Ctags // 5 | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ 6 | !_TAG_PROGRAM_VERSION 5.9~svn20110310 // 7 | METHOD_GET webbench.c 35;" d file: 8 | METHOD_HEAD webbench.c 36;" d file: 9 | METHOD_OPTIONS webbench.c 37;" d file: 10 | METHOD_TRACE webbench.c 38;" d file: 11 | PROGRAM_VERSION webbench.c 39;" d file: 12 | REQUEST_SIZE webbench.c 50;" d file: 13 | Socket socket.c /^int Socket(const char *host, int clientPort)$/;" f 14 | alarm_handler webbench.c /^static void alarm_handler(int signal)$/;" f file: 15 | bench webbench.c /^static int bench(void)$/;" f file: 16 | benchcore webbench.c /^void benchcore(const char *host,const int port,const char *req)$/;" f 17 | benchtime webbench.c /^int benchtime=30;$/;" v 18 | build_request webbench.c /^void build_request(const char *url)$/;" f 19 | bytes webbench.c /^int bytes=0;$/;" v 20 | clients webbench.c /^int clients=1;$/;" v 21 | failed webbench.c /^int failed=0;$/;" v 22 | force webbench.c /^int force=0;$/;" v 23 | force_reload webbench.c /^int force_reload=0;$/;" v 24 | host webbench.c /^char host[MAXHOSTNAMELEN];$/;" v 25 | http10 webbench.c /^int http10=1; \/* 0 - http\/0.9, 1 - http\/1.0, 2 - http\/1.1 *\/$/;" v 26 | long_options webbench.c /^static const struct option long_options[]=$/;" v typeref:struct:option file: 27 | main webbench.c /^int main(int argc, char *argv[])$/;" f 28 | method webbench.c /^int method=METHOD_GET;$/;" v 29 | mypipe webbench.c /^int mypipe[2];$/;" v 30 | proxyhost webbench.c /^char *proxyhost=NULL;$/;" v 31 | proxyport webbench.c /^int proxyport=80;$/;" v 32 | request webbench.c /^char request[REQUEST_SIZE];$/;" v 33 | speed webbench.c /^int speed=0;$/;" v 34 | timerexpired webbench.c /^volatile int timerexpired=0;$/;" v 35 | usage webbench.c /^static void usage(void)$/;" f file: 36 | -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/webbench: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/webbench-1.5/webbench -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/webbench-1.5.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/webbench-1.5/webbench-1.5.tar.gz -------------------------------------------------------------------------------- /TinyWebServer/webbench-1.5/webbench.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/TinyWebServer/webbench-1.5/webbench.o -------------------------------------------------------------------------------- /TinyWebServer/webserver.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBSERVER_H 2 | #define WEBSERVER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "./threadpool/threadpool.h" 16 | #include "./http/http_conn.h" 17 | 18 | const int MAX_FD = 65536; //最大文件描述符 19 | const int MAX_EVENT_NUMBER = 10000; //最大事件数 20 | const int TIMESLOT = 5; //最小超时单位 21 | 22 | class WebServer 23 | { 24 | public: 25 | WebServer(); 26 | ~WebServer(); 27 | 28 | void init(int port , string user, string passWord, string databaseName, 29 | int log_write , int opt_linger, int trigmode, int sql_num, 30 | int thread_num, int close_log, int actor_model); 31 | 32 | void thread_pool(); 33 | void sql_pool(); 34 | void log_write(); 35 | void trig_mode(); 36 | void eventListen(); 37 | void eventLoop(); 38 | void timer(int connfd, struct sockaddr_in client_address); 39 | void adjust_timer(util_timer *timer); 40 | void deal_timer(util_timer *timer, int sockfd); 41 | bool dealclinetdata(); 42 | bool dealwithsignal(bool& timeout, bool& stop_server); 43 | void dealwithread(int sockfd); 44 | void dealwithwrite(int sockfd); 45 | 46 | public: 47 | //基础 48 | int m_port; 49 | char *m_root; 50 | int m_log_write; 51 | int m_close_log; 52 | int m_actormodel; 53 | 54 | int m_pipefd[2]; 55 | int m_epollfd; 56 | http_conn *users; 57 | 58 | //数据库相关 59 | connection_pool *m_connPool; 60 | string m_user; //登陆数据库用户名 61 | string m_passWord; //登陆数据库密码 62 | string m_databaseName; //使用数据库名 63 | int m_sql_num; 64 | 65 | //线程池相关 66 | threadpool *m_pool; 67 | int m_thread_num; 68 | 69 | //epoll_event相关 70 | epoll_event events[MAX_EVENT_NUMBER]; 71 | 72 | int m_listenfd; 73 | int m_OPT_LINGER; 74 | int m_TRIGMode; 75 | int m_LISTENTrigmode; 76 | int m_CONNTrigmode; 77 | 78 | //定时器相关 79 | client_data *users_timer; 80 | Utils utils; 81 | }; 82 | #endif 83 | -------------------------------------------------------------------------------- /WebServerCpp11/.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: Google -------------------------------------------------------------------------------- /WebServerCpp11/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Otheres 35 | core 36 | .vscode 37 | -------------------------------------------------------------------------------- /WebServerCpp11/.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | sudo: required 3 | dist: trusty 4 | compiler: 5 | - g++ 6 | os: 7 | - linux 8 | install: 9 | - sudo apt-get install cmake 10 | env: 11 | - BUILD_TYPE=debug 12 | - BUILD_TYPE=release 13 | script: 14 | - ./build.sh 15 | 16 | -------------------------------------------------------------------------------- /WebServerCpp11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(WebServer CXX) 4 | 5 | if(NOT CMAKE_BUILD_TYPE) 6 | set(CMAKE_BUILD_TYPE "Debug") 7 | endif() 8 | 9 | set(CXX_FLAGS 10 | -g 11 | -Wall 12 | -std=c++11 13 | -D_PTHREADS 14 | -Wno-unused-parameter 15 | ) 16 | 17 | 18 | set(CMAKE_CXX_COMPILER "g++") 19 | set(CMAKE_CXX_FLAGS_DEBUG "-O0") 20 | set(CMAKE_CXX_FLAGS_RELEASE "-O0") 21 | 22 | string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") 23 | 24 | 25 | string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE) 26 | message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}}) 27 | 28 | add_subdirectory(WebServer) -------------------------------------------------------------------------------- /WebServerCpp11/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 林亚 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /WebServerCpp11/README.md: -------------------------------------------------------------------------------- 1 | # A C++ High Performance Web Server 2 | 3 | [![Build Status](https://travis-ci.org/linyacool/WebServer.svg?branch=master)](https://travis-ci.org/linyacool/WebServer) 4 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://opensource.org/licenses/MIT) 5 | 6 | 7 | ## Introduction 8 | 9 | 本项目为C++11编写的Web服务器,解析了get、head请求,可处理静态资源,支持HTTP长连接,支持管线化请求,并实现了异步日志,记录服务器运行状态。 10 | 11 | 测试页:http://www.linya.pub/ 12 | 13 | 14 | | Part Ⅰ | Part Ⅱ | Part Ⅲ | Part Ⅳ | Part Ⅴ | Part Ⅵ | 15 | | :--------: | :---------: | :---------: | :---------: | :---------: | :---------: | 16 | | [并发模型](https://github.com/linyacool/WebServer/blob/master/并发模型.md)|[连接的维护](https://github.com/linyacool/WebServer/blob/master/连接的维护.md)|[版本历史](https://github.com/linyacool/WebServer/blob/master/%E7%89%88%E6%9C%AC%E5%8E%86%E5%8F%B2.md) | [测试及改进](https://github.com/linyacool/WebServer/blob/master/测试及改进.md) | [项目目的](https://github.com/linyacool/WebServer/blob/master/%E9%A1%B9%E7%9B%AE%E7%9B%AE%E7%9A%84.md) | [面试问题](https://github.com/linyacool/WebServer/blob/master/%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98.md) 17 | 18 | ## Envoirment 19 | * OS: Ubuntu 14.04 20 | * Complier: g++ 4.8 21 | 22 | ## Build 23 | 24 | ./build.sh 25 | 26 | ## Usage 27 | 28 | ./WebServer [-t thread_numbers] [-p port] [-l log_file_path(should begin with '/')] 29 | 30 | ## Technical points 31 | * 使用Epoll边沿触发的IO多路复用技术,非阻塞IO,使用Reactor模式 32 | * 使用多线程充分利用多核CPU,并使用线程池避免线程频繁创建销毁的开销 33 | * 使用基于小根堆的定时器关闭超时请求 34 | * 主线程只负责accept请求,并以Round Robin的方式分发给其它IO线程(兼计算线程),锁的争用只会出现在主线程和某一特定线程中 35 | * 使用eventfd实现了线程的异步唤醒 36 | * 使用双缓冲区技术实现了简单的异步日志系统 37 | * 为减少内存泄漏的可能,使用智能指针等RAII机制 38 | * 使用状态机解析了HTTP请求,支持管线化 39 | * 支持优雅关闭连接 40 |   41 | ## Model 42 | 43 | 并发模型为Reactor+非阻塞IO+线程池,新连接Round Robin分配,详细介绍请参考[并发模型](https://github.com/linyacool/WebServer/blob/master/并发模型.md) 44 | ![并发模型](https://github.com/linyacool/WebServer/blob/master/datum/model.png) 45 | 46 | ## 代码统计 47 | 48 | ![cloc](https://github.com/linyacool/WebServer/blob/master/datum/cloc.png) 49 | 50 | 51 | ## Others 52 | 除了项目基本的代码,进服务器进行压测时,对开源测试工具Webbench增加了Keep-Alive选项和测试功能: 改写后的[Webbench](https://github.com/linyacool/WebBench) 53 | 54 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS?= -Wall -ggdb -W -O 2 | CC?= gcc 3 | LIBS?= 4 | LDFLAGS?= 5 | PREFIX?= /usr/local/webbench 6 | VERSION=1.5 7 | TMPDIR=/tmp/webbench-$(VERSION) 8 | 9 | all: webbench tags 10 | 11 | tags: *.c 12 | -ctags *.c 13 | 14 | install: webbench 15 | install -d $(DESTDIR)$(PREFIX)/bin 16 | install -s webbench $(DESTDIR)$(PREFIX)/bin 17 | ln -sf $(DESTDIR)$(PREFIX)/bin/webbench $(DESTDIR)/usr/local/bin/webbench 18 | 19 | install -d $(DESTDIR)/usr/local/man/man1 20 | install -d $(DESTDIR)$(PREFIX)/man/man1 21 | install -m 644 webbench.1 $(DESTDIR)$(PREFIX)/man/man1 22 | ln -sf $(DESTDIR)$(PREFIX)/man/man1/webbench.1 $(DESTDIR)/usr/local/man/man1/webbench.1 23 | 24 | install -d $(DESTDIR)$(PREFIX)/share/doc/webbench 25 | install -m 644 debian/copyright $(DESTDIR)$(PREFIX)/share/doc/webbench 26 | install -m 644 debian/changelog $(DESTDIR)$(PREFIX)/share/doc/webbench 27 | 28 | webbench: webbench.o Makefile 29 | $(CC) $(CFLAGS) $(LDFLAGS) -o webbench webbench.o $(LIBS) 30 | 31 | clean: 32 | -rm -f *.o webbench *~ core *.core tags 33 | 34 | tar: clean 35 | -debian/rules clean 36 | rm -rf $(TMPDIR) 37 | install -d $(TMPDIR) 38 | cp -p Makefile webbench.c socket.c webbench.1 $(TMPDIR) 39 | install -d $(TMPDIR)/debian 40 | -cp -p debian/* $(TMPDIR)/debian 41 | ln -sf debian/copyright $(TMPDIR)/COPYRIGHT 42 | ln -sf debian/changelog $(TMPDIR)/ChangeLog 43 | -cd $(TMPDIR) && cd .. && tar cozf webbench-$(VERSION).tar.gz webbench-$(VERSION) 44 | 45 | webbench.o: webbench.c socket.c Makefile 46 | 47 | .PHONY: clean install all tar 48 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/README.md: -------------------------------------------------------------------------------- 1 | # WebBench 2 | 3 | Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。 4 | 5 | ## 依赖 6 | ctags 7 | 8 | ## 使用: 9 | 10 | sudo make && sudo make install PREFIX=your_path_to_webbench 11 | 12 | ## 命令行选项: 13 | 14 | 15 | 16 | 17 | | 短参 | 长参数 | 作用 | 18 | | ------------- |:-------------:| -----:| 19 | |-f |--force |不需要等待服务器响应 | 20 | |-r |--reload |发送重新加载请求 | 21 | |-t |--time |运行多长时间,单位:秒" | 22 | |-p |--proxy |使用代理服务器来发送请求 | 23 | |-c |--clients |创建多少个客户端,默认1个" | 24 | |-9 |--http09 |使用 HTTP/0.9 | 25 | |-1 |--http10 |使用 HTTP/1.0 协议 | 26 | |-2 |--http11 |使用 HTTP/1.1 协议 | 27 | | |--get |使用 GET请求方法 | 28 | | |--head |使用 HEAD请求方法 | 29 | | |--options |使用 OPTIONS请求方法 | 30 | | |--trace |使用 TRACE请求方法 | 31 | |-?/-h |--help |打印帮助信息 | 32 | |-V |--version |显示版本号 | 33 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/bin/webbench: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/WebBench/bin/webbench -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/build.sh: -------------------------------------------------------------------------------- 1 | sudo make && sudo make install PREFIX=. -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/debian/changelog: -------------------------------------------------------------------------------- 1 | webbench (1.5) unstable; urgency=low 2 | 3 | * allow building with both Gnu and BSD make 4 | 5 | -- Radim Kolar Fri, Jun 25 12:00:20 CEST 2004 6 | 7 | webbench (1.4) unstable; urgency=low 8 | 9 | * check if url is not too long 10 | * report correct program version number 11 | * use yield() when waiting for test start 12 | * corrected error codes 13 | * check availability of test server first 14 | * do not abort test if first request failed 15 | * report when some childrens are dead. 16 | * use alarm, not time() for lower syscal use by bench 17 | * use mode 644 for installed doc 18 | * makefile cleaned for better freebsd ports integration 19 | 20 | -- Radim Kolar Thu, 15 Jan 2004 11:15:52 +0100 21 | 22 | webbench (1.3) unstable; urgency=low 23 | 24 | * Build fixes for freeBSD 25 | * Default benchmark time 60 -> 30 26 | * generate tar with subdirectory 27 | * added to freeBSD ports collection 28 | 29 | -- Radim Kolar Mon, 12 Jan 2004 17:00:24 +0100 30 | 31 | webbench (1.2) unstable; urgency=low 32 | 33 | * Only debian-related bugfixes 34 | * Updated Debian/rules 35 | * Adapted to fit new directory system 36 | * moved from debstd to dh_* 37 | 38 | -- Radim Kolar Fri, 18 Jan 2002 12:33:04 +0100 39 | 40 | webbench (1.1) unstable; urgency=medium 41 | 42 | * Program debianized 43 | * added support for multiple methods (GET, HEAD, OPTIONS, TRACE) 44 | * added support for multiple HTTP versions (0.9 -- 1.1) 45 | * added long options 46 | * added multiple clients 47 | * wait for start of second before test 48 | * test time can be specified 49 | * better error checking when reading reply from server 50 | * FIX: tests was one second longer than expected 51 | 52 | -- Radim Kolar Thu, 16 Sep 1999 18:48:00 +0200 53 | 54 | Local variables: 55 | mode: debian-changelog 56 | End: 57 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/debian/control: -------------------------------------------------------------------------------- 1 | Source: webbench 2 | Section: web 3 | Priority: extra 4 | Maintainer: Radim Kolar 5 | Build-Depends: debhelper (>> 3.0.0) 6 | Standards-Version: 3.5.2 7 | 8 | Package: webbench 9 | Architecture: any 10 | Depends: ${shlibs:Depends} 11 | Description: Simple forking Web benchmark 12 | webbench is very simple program for benchmarking WWW or Proxy servers. 13 | Uses fork() for simulating multiple clients load. Can use HTTP 0.9 - 1.1 14 | requests, but Keep-Alive connections are not supported. 15 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/debian/copyright: -------------------------------------------------------------------------------- 1 | Webbench was written by Radim Kolar 1997-2004 (hsn@netmag.cz). 2 | 3 | UNIX sockets code (socket.c) taken from popclient 1.5 4/1/94 4 | public domain code, created by Virginia Tech Computing Center. 5 | 6 | Copyright: GPL (see /usr/share/common-licenses/GPL) 7 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/debian/dirs: -------------------------------------------------------------------------------- 1 | usr/bin -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # Sample debian/rules that uses debhelper. 3 | # GNU copyright 1997 to 1999 by Joey Hess. 4 | 5 | # Uncomment this to turn on verbose mode. 6 | #export DH_VERBOSE=1 7 | 8 | # This is the debhelper compatability version to use. 9 | export DH_COMPAT=3 10 | 11 | configure: configure-stamp 12 | configure-stamp: 13 | dh_testdir 14 | touch configure-stamp 15 | 16 | build: configure-stamp build-stamp 17 | build-stamp: 18 | dh_testdir 19 | $(MAKE) 20 | touch build-stamp 21 | 22 | clean: 23 | dh_testdir 24 | rm -f build-stamp configure-stamp 25 | 26 | # Add here commands to clean up after the build process. 27 | -$(MAKE) clean 28 | 29 | dh_clean 30 | 31 | install: build 32 | dh_testdir 33 | dh_testroot 34 | dh_clean -k 35 | dh_installdirs 36 | 37 | # Add here commands to install the package into debian/webbench. 38 | $(MAKE) install DESTDIR=$(CURDIR)/debian/webbench 39 | 40 | 41 | # Build architecture-independent files here. 42 | binary-indep: build install 43 | # We have nothing to do by default. 44 | 45 | # Build architecture-dependent files here. 46 | binary-arch: build install 47 | dh_testdir 48 | dh_testroot 49 | dh_installdocs 50 | dh_installman webbench.1 51 | dh_installchangelogs 52 | dh_link 53 | dh_strip 54 | dh_compress 55 | dh_fixperms 56 | # dh_makeshlibs 57 | dh_installdeb 58 | dh_shlibdeps 59 | dh_gencontrol 60 | dh_md5sums 61 | dh_builddeb 62 | 63 | binary: binary-indep binary-arch 64 | .PHONY: build clean binary-indep binary-arch binary install configure 65 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/share/doc/webbench/changelog: -------------------------------------------------------------------------------- 1 | webbench (1.5) unstable; urgency=low 2 | 3 | * allow building with both Gnu and BSD make 4 | 5 | -- Radim Kolar Fri, Jun 25 12:00:20 CEST 2004 6 | 7 | webbench (1.4) unstable; urgency=low 8 | 9 | * check if url is not too long 10 | * report correct program version number 11 | * use yield() when waiting for test start 12 | * corrected error codes 13 | * check availability of test server first 14 | * do not abort test if first request failed 15 | * report when some childrens are dead. 16 | * use alarm, not time() for lower syscal use by bench 17 | * use mode 644 for installed doc 18 | * makefile cleaned for better freebsd ports integration 19 | 20 | -- Radim Kolar Thu, 15 Jan 2004 11:15:52 +0100 21 | 22 | webbench (1.3) unstable; urgency=low 23 | 24 | * Build fixes for freeBSD 25 | * Default benchmark time 60 -> 30 26 | * generate tar with subdirectory 27 | * added to freeBSD ports collection 28 | 29 | -- Radim Kolar Mon, 12 Jan 2004 17:00:24 +0100 30 | 31 | webbench (1.2) unstable; urgency=low 32 | 33 | * Only debian-related bugfixes 34 | * Updated Debian/rules 35 | * Adapted to fit new directory system 36 | * moved from debstd to dh_* 37 | 38 | -- Radim Kolar Fri, 18 Jan 2002 12:33:04 +0100 39 | 40 | webbench (1.1) unstable; urgency=medium 41 | 42 | * Program debianized 43 | * added support for multiple methods (GET, HEAD, OPTIONS, TRACE) 44 | * added support for multiple HTTP versions (0.9 -- 1.1) 45 | * added long options 46 | * added multiple clients 47 | * wait for start of second before test 48 | * test time can be specified 49 | * better error checking when reading reply from server 50 | * FIX: tests was one second longer than expected 51 | 52 | -- Radim Kolar Thu, 16 Sep 1999 18:48:00 +0200 53 | 54 | Local variables: 55 | mode: debian-changelog 56 | End: 57 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/share/doc/webbench/copyright: -------------------------------------------------------------------------------- 1 | Webbench was written by Radim Kolar 1997-2004 (hsn@netmag.cz). 2 | 3 | UNIX sockets code (socket.c) taken from popclient 1.5 4/1/94 4 | public domain code, created by Virginia Tech Computing Center. 5 | 6 | Copyright: GPL (see /usr/share/common-licenses/GPL) 7 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/socket.c: -------------------------------------------------------------------------------- 1 | /* $Id: socket.c 1.1 1995/01/01 07:11:14 cthuang Exp $ 2 | * 3 | * This module has been modified by Radim Kolar for OS/2 emx 4 | */ 5 | 6 | /*********************************************************************** 7 | module: socket.c 8 | program: popclient 9 | SCCS ID: @(#)socket.c 1.5 4/1/94 10 | programmer: Virginia Tech Computing Center 11 | compiler: DEC RISC C compiler (Ultrix 4.1) 12 | environment: DEC Ultrix 4.3 13 | description: UNIX sockets code. 14 | ***********************************************************************/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | int Socket(const char *host, int clientPort) 30 | { 31 | int sock; 32 | unsigned long inaddr; 33 | struct sockaddr_in ad; 34 | struct hostent *hp; 35 | 36 | memset(&ad, 0, sizeof(ad)); 37 | ad.sin_family = AF_INET; 38 | 39 | inaddr = inet_addr(host); 40 | if (inaddr != INADDR_NONE) 41 | memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr)); 42 | else 43 | { 44 | hp = gethostbyname(host); 45 | if (hp == NULL) 46 | return -1; 47 | memcpy(&ad.sin_addr, hp->h_addr, hp->h_length); 48 | } 49 | ad.sin_port = htons(clientPort); 50 | 51 | sock = socket(AF_INET, SOCK_STREAM, 0); 52 | 53 | 54 | if (sock < 0) 55 | return sock; 56 | 57 | // int optval = 1; 58 | // if(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1) 59 | // return -1; 60 | if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0) 61 | { 62 | close(sock); 63 | return -1; 64 | } 65 | 66 | return sock; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/test.sh: -------------------------------------------------------------------------------- 1 | ./bin/webbench -t 60 -c 1000 -2 --get http://127.0.0.1:80/hello -------------------------------------------------------------------------------- /WebServerCpp11/WebBench/webbench: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/WebBench/webbench -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS 2 | Channel.cpp 3 | Epoll.cpp 4 | EventLoop.cpp 5 | EventLoopThread.cpp 6 | EventLoopThreadPool.cpp 7 | HttpData.cpp 8 | Main.cpp 9 | Server.cpp 10 | #ThreadPool.cpp 11 | Timer.cpp 12 | Util.cpp 13 | ) 14 | include_directories(${PROJECT_SOURCE_DIR}/base) 15 | 16 | 17 | add_executable(WebServer ${SRCS}) 18 | target_link_libraries(WebServer libserver_base) 19 | 20 | 21 | add_subdirectory(base) 22 | add_subdirectory(tests) -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Channel.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Channel.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "Epoll.h" 12 | #include "EventLoop.h" 13 | #include "Util.h" 14 | 15 | using namespace std; 16 | 17 | Channel::Channel(EventLoop *loop) 18 | : loop_(loop), events_(0), lastEvents_(0), fd_(0) {} 19 | 20 | Channel::Channel(EventLoop *loop, int fd) 21 | : loop_(loop), fd_(fd), events_(0), lastEvents_(0) {} 22 | 23 | Channel::~Channel() { 24 | // loop_->poller_->epoll_del(fd, events_); 25 | // close(fd_); 26 | } 27 | 28 | int Channel::getFd() { return fd_; } 29 | void Channel::setFd(int fd) { fd_ = fd; } 30 | 31 | void Channel::handleRead() { 32 | if (readHandler_) { 33 | readHandler_(); 34 | } 35 | } 36 | 37 | void Channel::handleWrite() { 38 | if (writeHandler_) { 39 | writeHandler_(); 40 | } 41 | } 42 | 43 | void Channel::handleConn() { 44 | if (connHandler_) { 45 | connHandler_(); 46 | } 47 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Epoll.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Channel.h" 9 | #include "HttpData.h" 10 | #include "Timer.h" 11 | 12 | 13 | class Epoll { 14 | public: 15 | Epoll(); 16 | ~Epoll(); 17 | void epoll_add(SP_Channel request, int timeout); 18 | void epoll_mod(SP_Channel request, int timeout); 19 | void epoll_del(SP_Channel request); 20 | std::vector> poll(); 21 | std::vector> getEventsRequest(int events_num); 22 | void add_timer(std::shared_ptr request_data, int timeout); 23 | int getEpollFd() { return epollFd_; } 24 | void handleExpired(); 25 | 26 | private: 27 | static const int MAXFDS = 100000; 28 | int epollFd_; 29 | std::vector events_; 30 | std::shared_ptr fd2chan_[MAXFDS]; 31 | std::shared_ptr fd2http_[MAXFDS]; 32 | TimerManager timerManager_; 33 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/EventLoop.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include "Channel.h" 8 | #include "Epoll.h" 9 | #include "Util.h" 10 | #include "base/CurrentThread.h" 11 | #include "base/Logging.h" 12 | #include "base/Thread.h" 13 | 14 | 15 | #include 16 | using namespace std; 17 | 18 | class EventLoop { 19 | public: 20 | typedef std::function Functor; 21 | EventLoop(); 22 | ~EventLoop(); 23 | void loop(); 24 | void quit(); 25 | void runInLoop(Functor&& cb); 26 | void queueInLoop(Functor&& cb); 27 | bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); } 28 | void assertInLoopThread() { assert(isInLoopThread()); } 29 | void shutdown(shared_ptr channel) { shutDownWR(channel->getFd()); } 30 | void removeFromPoller(shared_ptr channel) { 31 | // shutDownWR(channel->getFd()); 32 | poller_->epoll_del(channel); 33 | } 34 | void updatePoller(shared_ptr channel, int timeout = 0) { 35 | poller_->epoll_mod(channel, timeout); 36 | } 37 | void addToPoller(shared_ptr channel, int timeout = 0) { 38 | poller_->epoll_add(channel, timeout); 39 | } 40 | 41 | private: 42 | // 声明顺序 wakeupFd_ > pwakeupChannel_ 43 | bool looping_; 44 | shared_ptr poller_; 45 | int wakeupFd_; 46 | bool quit_; 47 | bool eventHandling_; 48 | mutable MutexLock mutex_; 49 | std::vector pendingFunctors_; 50 | bool callingPendingFunctors_; 51 | const pid_t threadId_; 52 | shared_ptr pwakeupChannel_; 53 | 54 | void wakeup(); 55 | void handleRead(); 56 | void doPendingFunctors(); 57 | void handleConn(); 58 | }; 59 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/EventLoopThread.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "EventLoopThread.h" 4 | #include 5 | 6 | EventLoopThread::EventLoopThread() 7 | : loop_(NULL), 8 | exiting_(false), 9 | thread_(bind(&EventLoopThread::threadFunc, this), "EventLoopThread"), 10 | mutex_(), 11 | cond_(mutex_) {} 12 | 13 | EventLoopThread::~EventLoopThread() { 14 | exiting_ = true; 15 | if (loop_ != NULL) { 16 | loop_->quit(); 17 | thread_.join(); 18 | } 19 | } 20 | 21 | EventLoop* EventLoopThread::startLoop() { 22 | assert(!thread_.started()); 23 | thread_.start(); 24 | { 25 | MutexLockGuard lock(mutex_); 26 | // 一直等到threadFun在Thread里真正跑起来 27 | while (loop_ == NULL) cond_.wait(); 28 | } 29 | return loop_; 30 | } 31 | 32 | void EventLoopThread::threadFunc() { 33 | EventLoop loop; 34 | 35 | { 36 | MutexLockGuard lock(mutex_); 37 | loop_ = &loop; 38 | cond_.notify(); 39 | } 40 | 41 | loop.loop(); 42 | // assert(exiting_); 43 | loop_ = NULL; 44 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "EventLoop.h" 5 | #include "base/Condition.h" 6 | #include "base/MutexLock.h" 7 | #include "base/Thread.h" 8 | #include "base/noncopyable.h" 9 | 10 | 11 | class EventLoopThread : noncopyable { 12 | public: 13 | EventLoopThread(); 14 | ~EventLoopThread(); 15 | EventLoop* startLoop(); 16 | 17 | private: 18 | void threadFunc(); 19 | EventLoop* loop_; 20 | bool exiting_; 21 | Thread thread_; 22 | MutexLock mutex_; 23 | Condition cond_; 24 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/EventLoopThreadPool.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "EventLoopThreadPool.h" 4 | 5 | EventLoopThreadPool::EventLoopThreadPool(EventLoop *baseLoop, int numThreads) 6 | : baseLoop_(baseLoop), started_(false), numThreads_(numThreads), next_(0) { 7 | if (numThreads_ <= 0) { 8 | LOG << "numThreads_ <= 0"; 9 | abort(); 10 | } 11 | } 12 | 13 | void EventLoopThreadPool::start() { 14 | baseLoop_->assertInLoopThread(); 15 | started_ = true; 16 | for (int i = 0; i < numThreads_; ++i) { 17 | std::shared_ptr t(new EventLoopThread()); 18 | threads_.push_back(t); 19 | loops_.push_back(t->startLoop()); 20 | } 21 | } 22 | 23 | EventLoop *EventLoopThreadPool::getNextLoop() { 24 | baseLoop_->assertInLoopThread(); 25 | assert(started_); 26 | EventLoop *loop = baseLoop_; 27 | if (!loops_.empty()) { 28 | loop = loops_[next_]; 29 | next_ = (next_ + 1) % numThreads_; 30 | } 31 | return loop; 32 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/EventLoopThreadPool.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include "EventLoopThread.h" 7 | #include "base/Logging.h" 8 | #include "base/noncopyable.h" 9 | 10 | 11 | class EventLoopThreadPool : noncopyable { 12 | public: 13 | EventLoopThreadPool(EventLoop* baseLoop, int numThreads); 14 | 15 | ~EventLoopThreadPool() { LOG << "~EventLoopThreadPool()"; } 16 | void start(); 17 | 18 | EventLoop* getNextLoop(); 19 | 20 | private: 21 | EventLoop* baseLoop_; 22 | bool started_; 23 | int numThreads_; 24 | int next_; 25 | std::vector> threads_; 26 | std::vector loops_; 27 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Main.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include 4 | #include 5 | #include "EventLoop.h" 6 | #include "Server.h" 7 | #include "base/Logging.h" 8 | 9 | 10 | int main(int argc, char *argv[]) { 11 | int threadNum = 4; 12 | int port = 80; 13 | std::string logPath = "./WebServer.log"; 14 | 15 | // parse args 16 | int opt; 17 | const char *str = "t:l:p:"; 18 | while ((opt = getopt(argc, argv, str)) != -1) { 19 | switch (opt) { 20 | case 't': { 21 | threadNum = atoi(optarg); 22 | break; 23 | } 24 | case 'l': { 25 | logPath = optarg; 26 | if (logPath.size() < 2 || optarg[0] != '/') { 27 | printf("logPath should start with \"/\"\n"); 28 | abort(); 29 | } 30 | break; 31 | } 32 | case 'p': { 33 | port = atoi(optarg); 34 | break; 35 | } 36 | default: 37 | break; 38 | } 39 | } 40 | Logger::setLogFileName(logPath); 41 | // STL库在多线程上应用 42 | #ifndef _PTHREADS 43 | LOG << "_PTHREADS is not defined !"; 44 | #endif 45 | EventLoop mainLoop; 46 | Server myHTTPServer(&mainLoop, threadNum, port); 47 | myHTTPServer.start(); 48 | mainLoop.loop(); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Makefile: -------------------------------------------------------------------------------- 1 | # MAINSOURCE代表含有main入口函数的cpp文件,因为含有测试代码, 2 | # 所以要为多个目标编译,这里把Makefile写的通用了一点, 3 | # 以后加东西Makefile不用做多少改动 4 | MAINSOURCE := Main.cpp base/tests/LoggingTest.cpp tests/HTTPClient.cpp 5 | # MAINOBJS := $(patsubst %.cpp,%.o,$(MAINSOURCE)) 6 | SOURCE := $(wildcard *.cpp base/*.cpp tests/*.cpp) 7 | override SOURCE := $(filter-out $(MAINSOURCE),$(SOURCE)) 8 | OBJS := $(patsubst %.cpp,%.o,$(SOURCE)) 9 | 10 | TARGET := WebServer 11 | CC := g++ 12 | LIBS := -lpthread 13 | INCLUDE:= -I./usr/local/lib 14 | CFLAGS := -std=c++11 -g -Wall -O3 -D_PTHREADS 15 | CXXFLAGS:= $(CFLAGS) 16 | 17 | # Test object 18 | SUBTARGET1 := LoggingTest 19 | SUBTARGET2 := HTTPClient 20 | 21 | .PHONY : objs clean veryclean rebuild all tests debug 22 | all : $(TARGET) $(SUBTARGET1) $(SUBTARGET2) 23 | objs : $(OBJS) 24 | rebuild: veryclean all 25 | 26 | tests : $(SUBTARGET1) $(SUBTARGET2) 27 | clean : 28 | find . -name '*.o' | xargs rm -f 29 | veryclean : 30 | find . -name '*.o' | xargs rm -f 31 | find . -name $(TARGET) | xargs rm -f 32 | find . -name $(SUBTARGET1) | xargs rm -f 33 | find . -name $(SUBTARGET2) | xargs rm -f 34 | debug: 35 | @echo $(SOURCE) 36 | 37 | $(TARGET) : $(OBJS) Main.o 38 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 39 | # $@代表目标,这里是$(TARGET) 40 | 41 | $(SUBTARGET1) : $(OBJS) base/tests/LoggingTest.o 42 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 43 | 44 | $(SUBTARGET2) : $(OBJS) tests/HTTPClient.o 45 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 46 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Makefile.bak: -------------------------------------------------------------------------------- 1 | # @Author Lin Ya 2 | # @Email xxbbb@vip.qq.com 3 | # MAINSOURCE代表含有main入口函数的cpp文件,因为含有测试代码, 4 | # 所以要为多个目标编译,这里把Makefile写的通用了一点, 5 | # 以后加东西Makefile不用做多少改动 6 | MAINSOURCE := Main.cpp base/tests/LoggingTest.cpp tests/HTTPClient.cpp 7 | # MAINOBJS := $(patsubst %.cpp,%.o,$(MAINSOURCE)) 8 | SOURCE := $(wildcard *.cpp base/*.cpp tests/*.cpp) 9 | override SOURCE := $(filter-out $(MAINSOURCE),$(SOURCE)) 10 | OBJS := $(patsubst %.cpp,%.o,$(SOURCE)) 11 | 12 | TARGET := WebServer 13 | CC := g++ 14 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs 15 | INCLUDE:= -I./usr/local/lib 16 | CFLAGS := -std=c++11 -g -Wall -O3 -D_PTHREADS 17 | CXXFLAGS:= $(CFLAGS) 18 | 19 | # Test object 20 | SUBTARGET1 := LoggingTest 21 | SUBTARGET2 := HTTPClient 22 | 23 | .PHONY : objs clean veryclean rebuild all tests debug 24 | all : $(TARGET) $(SUBTARGET1) $(SUBTARGET2) 25 | objs : $(OBJS) 26 | rebuild: veryclean all 27 | 28 | tests : $(SUBTARGET1) $(SUBTARGET2) 29 | clean : 30 | find . -name '*.o' | xargs rm -f 31 | veryclean : 32 | find . -name '*.o' | xargs rm -f 33 | find . -name $(TARGET) | xargs rm -f 34 | find . -name $(SUBTARGET1) | xargs rm -f 35 | find . -name $(SUBTARGET2) | xargs rm -f 36 | debug: 37 | @echo $(SOURCE) 38 | 39 | $(TARGET) : $(OBJS) Main.o 40 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 41 | # $@代表目标,这里是$(TARGET) 42 | 43 | $(SUBTARGET1) : $(OBJS) base/tests/LoggingTest.o 44 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 45 | 46 | $(SUBTARGET2) : $(OBJS) tests/HTTPClient.o 47 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Server.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include "Channel.h" 6 | #include "EventLoop.h" 7 | #include "EventLoopThreadPool.h" 8 | 9 | class Server { 10 | public: 11 | Server(EventLoop *loop, int threadNum, int port); 12 | ~Server() {} 13 | EventLoop *getLoop() const { return loop_; } 14 | void start(); 15 | void handNewConn(); 16 | void handThisConn() { loop_->updatePoller(acceptChannel_); } 17 | 18 | private: 19 | EventLoop *loop_; 20 | int threadNum_; 21 | std::unique_ptr eventLoopThreadPool_; 22 | bool started_; 23 | std::shared_ptr acceptChannel_; 24 | int port_; 25 | int listenFd_; 26 | static const int MAXFDS = 100000; 27 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/ThreadPool.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | 4 | // This file has not been used 5 | #pragma once 6 | #include "Channel.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | const int THREADPOOL_INVALID = -1; 13 | const int THREADPOOL_LOCK_FAILURE = -2; 14 | const int THREADPOOL_QUEUE_FULL = -3; 15 | const int THREADPOOL_SHUTDOWN = -4; 16 | const int THREADPOOL_THREAD_FAILURE = -5; 17 | const int THREADPOOL_GRACEFUL = 1; 18 | 19 | const int MAX_THREADS = 1024; 20 | const int MAX_QUEUE = 65535; 21 | 22 | typedef enum 23 | { 24 | immediate_shutdown = 1, 25 | graceful_shutdown = 2 26 | } ShutDownOption; 27 | 28 | struct ThreadPoolTask 29 | { 30 | std::function)> fun; 31 | std::shared_ptr args; 32 | }; 33 | 34 | 35 | class ThreadPool 36 | { 37 | private: 38 | static pthread_mutex_t lock; 39 | static pthread_cond_t notify; 40 | 41 | static std::vector threads; 42 | static std::vector queue; 43 | static int thread_count; 44 | static int queue_size; 45 | static int head; 46 | // tail 指向尾节点的下一节点 47 | static int tail; 48 | static int count; 49 | static int shutdown; 50 | static int started; 51 | public: 52 | static int threadpool_create(int _thread_count, int _queue_size); 53 | static int threadpool_add(std::shared_ptr args, std::function)> fun); 54 | static int threadpool_destroy(ShutDownOption shutdown_option = graceful_shutdown); 55 | static int threadpool_free(); 56 | static void *threadpool_thread(void *args); 57 | }; 58 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Timer.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "HttpData.h" 9 | #include "base/MutexLock.h" 10 | #include "base/noncopyable.h" 11 | 12 | 13 | class HttpData; 14 | 15 | class TimerNode { 16 | public: 17 | TimerNode(std::shared_ptr requestData, int timeout); 18 | ~TimerNode(); 19 | TimerNode(TimerNode &tn); 20 | void update(int timeout); 21 | bool isValid(); 22 | void clearReq(); 23 | void setDeleted() { deleted_ = true; } 24 | bool isDeleted() const { return deleted_; } 25 | size_t getExpTime() const { return expiredTime_; } 26 | 27 | private: 28 | bool deleted_; 29 | size_t expiredTime_; 30 | std::shared_ptr SPHttpData; 31 | }; 32 | 33 | struct TimerCmp { 34 | bool operator()(std::shared_ptr &a, 35 | std::shared_ptr &b) const { 36 | return a->getExpTime() > b->getExpTime(); 37 | } 38 | }; 39 | 40 | class TimerManager { 41 | public: 42 | TimerManager(); 43 | ~TimerManager(); 44 | void addTimer(std::shared_ptr SPHttpData, int timeout); 45 | void handleExpiredEvent(); 46 | 47 | private: 48 | typedef std::shared_ptr SPTimerNode; 49 | std::priority_queue, TimerCmp> 50 | timerNodeQueue; 51 | // MutexLock lock; 52 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/Util.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | 7 | ssize_t readn(int fd, void *buff, size_t n); 8 | ssize_t readn(int fd, std::string &inBuffer, bool &zero); 9 | ssize_t readn(int fd, std::string &inBuffer); 10 | ssize_t writen(int fd, void *buff, size_t n); 11 | ssize_t writen(int fd, std::string &sbuff); 12 | void handle_for_sigpipe(); 13 | int setSocketNonBlocking(int fd); 14 | void setSocketNodelay(int fd); 15 | void setSocketNoLinger(int fd); 16 | void shutDownWR(int fd); 17 | int socket_bind_listen(int port); -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/AsyncLogging.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include "CountDownLatch.h" 8 | #include "LogStream.h" 9 | #include "MutexLock.h" 10 | #include "Thread.h" 11 | #include "noncopyable.h" 12 | 13 | 14 | class AsyncLogging : noncopyable { 15 | public: 16 | AsyncLogging(const std::string basename, int flushInterval = 2); 17 | ~AsyncLogging() { 18 | if (running_) stop(); 19 | } 20 | void append(const char* logline, int len); 21 | 22 | void start() { 23 | running_ = true; 24 | thread_.start(); 25 | latch_.wait(); 26 | } 27 | 28 | void stop() { 29 | running_ = false; 30 | cond_.notify(); 31 | thread_.join(); 32 | } 33 | 34 | private: 35 | void threadFunc(); 36 | typedef FixedBuffer Buffer; 37 | typedef std::vector> BufferVector; 38 | typedef std::shared_ptr BufferPtr; 39 | const int flushInterval_; 40 | bool running_; 41 | std::string basename_; 42 | Thread thread_; 43 | MutexLock mutex_; 44 | Condition cond_; 45 | BufferPtr currentBuffer_; 46 | BufferPtr nextBuffer_; 47 | BufferVector buffers_; 48 | CountDownLatch latch_; 49 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIB_SRC 2 | AsyncLogging.cpp 3 | CountDownLatch.cpp 4 | FileUtil.cpp 5 | LogFile.cpp 6 | Logging.cpp 7 | LogStream.cpp 8 | Thread.cpp 9 | ) 10 | 11 | add_library(libserver_base ${LIB_SRC}) 12 | target_link_libraries(libserver_base pthread rt) 13 | 14 | set_target_properties(libserver_base PROPERTIES OUTPUT_NAME "server_base") 15 | 16 | add_subdirectory(tests) -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/Condition.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "MutexLock.h" 10 | #include "noncopyable.h" 11 | 12 | 13 | class Condition : noncopyable { 14 | public: 15 | explicit Condition(MutexLock &_mutex) : mutex(_mutex) { 16 | pthread_cond_init(&cond, NULL); 17 | } 18 | ~Condition() { pthread_cond_destroy(&cond); } 19 | void wait() { pthread_cond_wait(&cond, mutex.get()); } 20 | void notify() { pthread_cond_signal(&cond); } 21 | void notifyAll() { pthread_cond_broadcast(&cond); } 22 | bool waitForSeconds(int seconds) { 23 | struct timespec abstime; 24 | clock_gettime(CLOCK_REALTIME, &abstime); 25 | abstime.tv_sec += static_cast(seconds); 26 | return ETIMEDOUT == pthread_cond_timedwait(&cond, mutex.get(), &abstime); 27 | } 28 | 29 | private: 30 | MutexLock &mutex; 31 | pthread_cond_t cond; 32 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/CountDownLatch.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "CountDownLatch.h" 4 | 5 | CountDownLatch::CountDownLatch(int count) 6 | : mutex_(), condition_(mutex_), count_(count) {} 7 | 8 | void CountDownLatch::wait() { 9 | MutexLockGuard lock(mutex_); 10 | while (count_ > 0) condition_.wait(); 11 | } 12 | 13 | void CountDownLatch::countDown() { 14 | MutexLockGuard lock(mutex_); 15 | --count_; 16 | if (count_ == 0) condition_.notifyAll(); 17 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "Condition.h" 5 | #include "MutexLock.h" 6 | #include "noncopyable.h" 7 | 8 | // CountDownLatch的主要作用是确保Thread中传进去的func真的启动了以后 9 | // 外层的start才返回 10 | class CountDownLatch : noncopyable { 11 | public: 12 | explicit CountDownLatch(int count); 13 | void wait(); 14 | void countDown(); 15 | 16 | private: 17 | mutable MutexLock mutex_; 18 | Condition condition_; 19 | int count_; 20 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/CurrentThread.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | 6 | namespace CurrentThread { 7 | // internal 8 | extern __thread int t_cachedTid; 9 | extern __thread char t_tidString[32]; 10 | extern __thread int t_tidStringLength; 11 | extern __thread const char* t_threadName; 12 | void cacheTid(); 13 | inline int tid() { 14 | if (__builtin_expect(t_cachedTid == 0, 0)) { 15 | cacheTid(); 16 | } 17 | return t_cachedTid; 18 | } 19 | 20 | inline const char* tidString() // for logging 21 | { 22 | return t_tidString; 23 | } 24 | 25 | inline int tidStringLength() // for logging 26 | { 27 | return t_tidStringLength; 28 | } 29 | 30 | inline const char* name() { return t_threadName; } 31 | } 32 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/FileUtil.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "FileUtil.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | AppendFile::AppendFile(string filename) : fp_(fopen(filename.c_str(), "ae")) { 14 | // 用户提供缓冲区 15 | setbuffer(fp_, buffer_, sizeof buffer_); 16 | } 17 | 18 | AppendFile::~AppendFile() { fclose(fp_); } 19 | 20 | void AppendFile::append(const char* logline, const size_t len) { 21 | size_t n = this->write(logline, len); 22 | size_t remain = len - n; 23 | while (remain > 0) { 24 | size_t x = this->write(logline + n, remain); 25 | if (x == 0) { 26 | int err = ferror(fp_); 27 | if (err) fprintf(stderr, "AppendFile::append() failed !\n"); 28 | break; 29 | } 30 | n += x; 31 | remain = len - n; 32 | } 33 | } 34 | 35 | void AppendFile::flush() { fflush(fp_); } 36 | 37 | size_t AppendFile::write(const char* logline, size_t len) { 38 | return fwrite_unlocked(logline, 1, len, fp_); 39 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/FileUtil.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include "noncopyable.h" 6 | 7 | 8 | class AppendFile : noncopyable { 9 | public: 10 | explicit AppendFile(std::string filename); 11 | ~AppendFile(); 12 | // append 会向文件写 13 | void append(const char *logline, const size_t len); 14 | void flush(); 15 | 16 | private: 17 | size_t write(const char *logline, size_t len); 18 | FILE *fp_; 19 | char buffer_[64 * 1024]; 20 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/LogFile.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "LogFile.h" 4 | #include 5 | #include 6 | #include 7 | #include "FileUtil.h" 8 | 9 | 10 | using namespace std; 11 | 12 | LogFile::LogFile(const string& basename, int flushEveryN) 13 | : basename_(basename), 14 | flushEveryN_(flushEveryN), 15 | count_(0), 16 | mutex_(new MutexLock) { 17 | // assert(basename.find('/') >= 0); 18 | file_.reset(new AppendFile(basename)); 19 | } 20 | 21 | LogFile::~LogFile() {} 22 | 23 | void LogFile::append(const char* logline, int len) { 24 | MutexLockGuard lock(*mutex_); 25 | append_unlocked(logline, len); 26 | } 27 | 28 | void LogFile::flush() { 29 | MutexLockGuard lock(*mutex_); 30 | file_->flush(); 31 | } 32 | 33 | void LogFile::append_unlocked(const char* logline, int len) { 34 | file_->append(logline, len); 35 | ++count_; 36 | if (count_ >= flushEveryN_) { 37 | count_ = 0; 38 | file_->flush(); 39 | } 40 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/LogFile.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include "FileUtil.h" 7 | #include "MutexLock.h" 8 | #include "noncopyable.h" 9 | 10 | 11 | // TODO 提供自动归档功能 12 | class LogFile : noncopyable { 13 | public: 14 | // 每被append flushEveryN次,flush一下,会往文件写,只不过,文件也是带缓冲区的 15 | LogFile(const std::string& basename, int flushEveryN = 1024); 16 | ~LogFile(); 17 | 18 | void append(const char* logline, int len); 19 | void flush(); 20 | bool rollFile(); 21 | 22 | private: 23 | void append_unlocked(const char* logline, int len); 24 | 25 | const std::string basename_; 26 | const int flushEveryN_; 27 | 28 | int count_; 29 | std::unique_ptr mutex_; 30 | std::unique_ptr file_; 31 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/Logging.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Logging.h" 4 | #include "CurrentThread.h" 5 | #include "Thread.h" 6 | #include "AsyncLogging.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | static pthread_once_t once_control_ = PTHREAD_ONCE_INIT; 14 | static AsyncLogging *AsyncLogger_; 15 | 16 | std::string Logger::logFileName_ = "./WebServer.log"; 17 | 18 | void once_init() 19 | { 20 | AsyncLogger_ = new AsyncLogging(Logger::getLogFileName()); 21 | AsyncLogger_->start(); 22 | } 23 | 24 | void output(const char* msg, int len) 25 | { 26 | pthread_once(&once_control_, once_init); 27 | AsyncLogger_->append(msg, len); 28 | } 29 | 30 | Logger::Impl::Impl(const char *fileName, int line) 31 | : stream_(), 32 | line_(line), 33 | basename_(fileName) 34 | { 35 | formatTime(); 36 | } 37 | 38 | void Logger::Impl::formatTime() 39 | { 40 | struct timeval tv; 41 | time_t time; 42 | char str_t[26] = {0}; 43 | gettimeofday (&tv, NULL); 44 | time = tv.tv_sec; 45 | struct tm* p_time = localtime(&time); 46 | strftime(str_t, 26, "%Y-%m-%d %H:%M:%S\n", p_time); 47 | stream_ << str_t; 48 | } 49 | 50 | Logger::Logger(const char *fileName, int line) 51 | : impl_(fileName, line) 52 | { } 53 | 54 | Logger::~Logger() 55 | { 56 | impl_.stream_ << " -- " << impl_.basename_ << ':' << impl_.line_ << '\n'; 57 | const LogStream::Buffer& buf(stream().buffer()); 58 | output(buf.data(), buf.length()); 59 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/Logging.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "LogStream.h" 9 | 10 | 11 | class AsyncLogging; 12 | 13 | class Logger { 14 | public: 15 | Logger(const char *fileName, int line); 16 | ~Logger(); 17 | LogStream &stream() { return impl_.stream_; } 18 | 19 | static void setLogFileName(std::string fileName) { logFileName_ = fileName; } 20 | static std::string getLogFileName() { return logFileName_; } 21 | 22 | private: 23 | class Impl { 24 | public: 25 | Impl(const char *fileName, int line); 26 | void formatTime(); 27 | 28 | LogStream stream_; 29 | int line_; 30 | std::string basename_; 31 | }; 32 | Impl impl_; 33 | static std::string logFileName_; 34 | }; 35 | 36 | #define LOG Logger(__FILE__, __LINE__).stream() -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/Log的设计.txt: -------------------------------------------------------------------------------- 1 | Log的设计仿照了muduo库的设计,但我写的没那么复杂 2 | https://github.com/chenshuo/muduo 3 | 4 | 与Log相关的类包括FileUtil、LogFile、AsyncLogging、LogStream、Logging。 5 | 其中前4个类每一个类都含有一个append函数,Log的设计也是主要围绕这个append函数展开的。 6 | 7 | FileUtil是最底层的文件类,封装了Log文件的打开、写入并在类析构的时候关闭文件,底层使用了标准IO,该append函数直接向文件写。 8 | LogFile进一步封装了FileUtil,并设置了一个循环次数,没过这么多次就flush一次。 9 | AsyncLogging是核心,它负责启动一个log线程,专门用来将log写入LogFile,应用了“双缓冲技术”,其实有4个以上的缓冲区,但思想是一样的。 10 | AsyncLogging负责(定时到或被填满时)将缓冲区中的数据写入LogFile中。 11 | LogStream主要用来格式化输出,重载了<<运算符,同时也有自己的一块缓冲区,这里缓冲区的存在是为了缓存一行,把多个<<的结果连成一块。 12 | Logging是对外接口,Logging类内涵一个LogStream对象,主要是为了每次打log的时候在log之前和之后加上固定的格式化的信息,比如打log的行、 13 | 文件名等信息。 14 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/MutexLock.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include "noncopyable.h" 7 | 8 | 9 | class MutexLock : noncopyable { 10 | public: 11 | MutexLock() { pthread_mutex_init(&mutex, NULL); } 12 | ~MutexLock() { 13 | pthread_mutex_lock(&mutex); 14 | pthread_mutex_destroy(&mutex); 15 | } 16 | void lock() { pthread_mutex_lock(&mutex); } 17 | void unlock() { pthread_mutex_unlock(&mutex); } 18 | pthread_mutex_t *get() { return &mutex; } 19 | 20 | private: 21 | pthread_mutex_t mutex; 22 | 23 | // 友元类不受访问权限影响 24 | private: 25 | friend class Condition; 26 | }; 27 | 28 | class MutexLockGuard : noncopyable { 29 | public: 30 | explicit MutexLockGuard(MutexLock &_mutex) : mutex(_mutex) { mutex.lock(); } 31 | ~MutexLockGuard() { mutex.unlock(); } 32 | 33 | private: 34 | MutexLock &mutex; 35 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/Thread.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "CountDownLatch.h" 11 | #include "noncopyable.h" 12 | 13 | class Thread : noncopyable { 14 | public: 15 | typedef std::function ThreadFunc; 16 | explicit Thread(const ThreadFunc&, const std::string& name = std::string()); 17 | ~Thread(); 18 | void start(); 19 | int join(); 20 | bool started() const { return started_; } 21 | pid_t tid() const { return tid_; } 22 | const std::string& name() const { return name_; } 23 | 24 | private: 25 | void setDefaultName(); 26 | bool started_; 27 | bool joined_; 28 | pthread_t pthreadId_; 29 | pid_t tid_; 30 | ThreadFunc func_; 31 | std::string name_; 32 | CountDownLatch latch_; 33 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/noncopyable.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | 5 | class noncopyable { 6 | protected: 7 | noncopyable() {} 8 | ~noncopyable() {} 9 | 10 | private: 11 | noncopyable(const noncopyable&); 12 | const noncopyable& operator=(const noncopyable&); 13 | }; -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(LoggingTest LoggingTest.cpp) 2 | target_link_libraries(LoggingTest libserver_base) -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/base/tests/LoggingTest.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "../Logging.h" 4 | #include "../Thread.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | void threadFunc() 13 | { 14 | for (int i = 0; i < 100000; ++i) 15 | { 16 | LOG << i; 17 | } 18 | } 19 | 20 | void type_test() 21 | { 22 | // 13 lines 23 | cout << "----------type test-----------" << endl; 24 | LOG << 0; 25 | LOG << 1234567890123; 26 | LOG << 1.0f; 27 | LOG << 3.1415926; 28 | LOG << (short) 1; 29 | LOG << (long long) 1; 30 | LOG << (unsigned int) 1; 31 | LOG << (unsigned long) 1; 32 | LOG << (long double) 1.6555556; 33 | LOG << (unsigned long long) 1; 34 | LOG << 'c'; 35 | LOG << "abcdefg"; 36 | LOG << string("This is a string"); 37 | } 38 | 39 | void stressing_single_thread() 40 | { 41 | // 100000 lines 42 | cout << "----------stressing test single thread-----------" << endl; 43 | for (int i = 0; i < 100000; ++i) 44 | { 45 | LOG << i; 46 | } 47 | } 48 | 49 | void stressing_multi_threads(int threadNum = 4) 50 | { 51 | // threadNum * 100000 lines 52 | cout << "----------stressing test multi thread-----------" << endl; 53 | vector> vsp; 54 | for (int i = 0; i < threadNum; ++i) 55 | { 56 | shared_ptr tmp(new Thread(threadFunc, "testFunc")); 57 | vsp.push_back(tmp); 58 | } 59 | for (int i = 0; i < threadNum; ++i) 60 | { 61 | vsp[i]->start(); 62 | } 63 | sleep(3); 64 | } 65 | 66 | void other() 67 | { 68 | // 1 line 69 | cout << "----------other test-----------" << endl; 70 | LOG << "fddsa" << 'c' << 0 << 3.666 << string("This is a string"); 71 | } 72 | 73 | 74 | int main() 75 | { 76 | // 共500014行 77 | type_test(); 78 | sleep(3); 79 | 80 | stressing_single_thread(); 81 | sleep(3); 82 | 83 | other(); 84 | sleep(3); 85 | 86 | stressing_multi_threads(); 87 | sleep(3); 88 | return 0; 89 | } -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | -------------------------------------------------------------------------------- /WebServerCpp11/WebServer/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(HTTPClient HTTPClient.cpp) -------------------------------------------------------------------------------- /WebServerCpp11/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | SOURCE_DIR=`pwd` 6 | BUILD_DIR=${BUILD_DIR:-../build} 7 | BUILD_TYPE=${BUILD_TYPE:-Debug} 8 | 9 | mkdir -p $BUILD_DIR/$BUILD_TYPE \ 10 | && cd $BUILD_DIR/$BUILD_TYPE \ 11 | && cmake \ 12 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 13 | $SOURCE_DIR \ 14 | && make $* -------------------------------------------------------------------------------- /WebServerCpp11/datum/WebServer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/WebServer.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/WebServerk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/WebServerk.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/cloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/cloc.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/close.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/gdb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/gdb.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/idle.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/keepalive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/keepalive.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/model.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/muduo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/muduo.png -------------------------------------------------------------------------------- /WebServerCpp11/datum/muduok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/datum/muduok.png -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(wildcard *.cpp) 2 | OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE))) 3 | 4 | TARGET := myserver 5 | CC := g++ 6 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui 7 | INCLUDE:= -I./usr/local/include/opencv 8 | CFLAGS := -std=c++11 -g -Wall -O3 $(INCLUDE) 9 | CXXFLAGS:= $(CFLAGS) 10 | 11 | .PHONY : objs clean veryclean rebuild all 12 | all : $(TARGET) 13 | objs : $(OBJS) 14 | rebuild: veryclean all 15 | clean : 16 | rm -fr *.o 17 | veryclean : clean 18 | rm -rf $(TARGET) 19 | 20 | $(TARGET) : $(OBJS) 21 | $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/Makefile1: -------------------------------------------------------------------------------- 1 | cc=g++ -std=c++11 2 | main: main.o requestData.o epoll.o threadpool.o 3 | $(cc) -o main main.o requestData.o epoll.o threadpool.o -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml 4 | main.o: main.cpp 5 | $(cc) -I/usr/local/include/opencv -c main.cpp 6 | requestData.o: requestData.h requestData.cpp 7 | $(cc) -I/usr/local/include/opencv -c requestData.cpp 8 | epoll.o: epoll.h epoll.cpp 9 | $(cc) -I/usr/local/include/opencv -c epoll.cpp 10 | threadpool.o: threadpool.h threadpool.cpp 11 | $(cc) -I/usr/local/include/opencv -c threadpool.cpp 12 | .PHONY: clean 13 | clean: 14 | -rm main *.o 15 | 16 | 17 | 18 | 19 | .PHONY : everything objs clean veryclean rebuild 20 | everything : 21 | $(TARGET) 22 | all : 23 | $(TARGET) 24 | objs : 25 | $(OBJS) 26 | rebuild: 27 | veryclean everything 28 | clean : 29 | rm -fr *.o 30 | veryclean : 31 | clean rm -fr $(TARGET) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/epoll.cpp: -------------------------------------------------------------------------------- 1 | #include "epoll.h" 2 | #include 3 | #include 4 | #include "threadpool.h" 5 | 6 | struct epoll_event* events; 7 | 8 | int epoll_init() 9 | { 10 | int epoll_fd = epoll_create(LISTENQ + 1); 11 | if(epoll_fd == -1) 12 | return -1; 13 | //events = (struct epoll_event*)malloc(sizeof(struct epoll_event) * MAXEVENTS); 14 | events = new epoll_event[MAXEVENTS]; 15 | return epoll_fd; 16 | } 17 | 18 | // 注册新描述符 19 | int epoll_add(int epoll_fd, int fd, void *request, __uint32_t events) 20 | { 21 | struct epoll_event event; 22 | event.data.ptr = request; 23 | event.events = events; 24 | //printf("add to epoll %d\n", fd); 25 | if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event) < 0) 26 | { 27 | perror("epoll_add error"); 28 | return -1; 29 | } 30 | return 0; 31 | } 32 | 33 | // 修改描述符状态 34 | int epoll_mod(int epoll_fd, int fd, void *request, __uint32_t events) 35 | { 36 | struct epoll_event event; 37 | event.data.ptr = request; 38 | event.events = events; 39 | if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &event) < 0) 40 | { 41 | perror("epoll_mod error"); 42 | return -1; 43 | } 44 | return 0; 45 | } 46 | 47 | // 从epoll中删除描述符 48 | int epoll_del(int epoll_fd, int fd, void *request, __uint32_t events) 49 | { 50 | struct epoll_event event; 51 | event.data.ptr = request; 52 | event.events = events; 53 | if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event) < 0) 54 | { 55 | perror("epoll_del error"); 56 | return -1; 57 | } 58 | return 0; 59 | } 60 | 61 | // 返回活跃事件数 62 | int my_epoll_wait(int epoll_fd, struct epoll_event* events, int max_events, int timeout) 63 | { 64 | int ret_count = epoll_wait(epoll_fd, events, max_events, timeout); 65 | if (ret_count < 0) 66 | { 67 | perror("epoll wait error"); 68 | } 69 | return ret_count; 70 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/epoll.h: -------------------------------------------------------------------------------- 1 | #ifndef EVENTPOLL 2 | #define EVENTPOLL 3 | #include "requestData.h" 4 | 5 | const int MAXEVENTS = 5000; 6 | const int LISTENQ = 1024; 7 | 8 | int epoll_init(); 9 | int epoll_add(int epoll_fd, int fd, void *request, __uint32_t events); 10 | int epoll_mod(int epoll_fd, int fd, void *request, __uint32_t events); 11 | int epoll_del(int epoll_fd, int fd, void *request, __uint32_t events); 12 | int my_epoll_wait(int epoll_fd, struct epoll_event *events, int max_events, int timeout); 13 | 14 | #endif -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/improvement.txt: -------------------------------------------------------------------------------- 1 | 1. 指针可以改成shared_ptr,不需要delete。 2 | 2. 想法在某些地方写成单例模式。 3 | 3. readn 和 writen 改成写到不能写后或读到不能读后加入epoll等待,要记录写到哪或读到哪,维护这样一个状态。比较两者的性能差异。 4 | 4. 信号处理部分可以将 epoll_wait 替换为更安全的 epoll_pwait。 5 | 6 | 7 | 踩坑: 8 | 1. 对EPOLLONESHOT的误解,原以为当epoll_wait监听到相应的事件触发后,epoll会把与事件关联的fd从epoll描述符中禁止掉并且彻底删除,实际上并不会删除,man手册上的解释如下: 9 | EPOLLONESHOT (since Linux 2.6.2) 10 | Sets the one-shot behavior for the associated file descriptor. 11 | This means that after an event is pulled out with 12 | epoll_wait(2) the associated file descriptor is internally 13 | disabled and no other events will be reported by the epoll 14 | interface. The user must call epoll_ctl() with EPOLL_CTL_MOD 15 | to rearm the file descriptor with a new event mask. 16 | 另外: 17 | Linux Programmer's Manual 中第六个问题: 18 | Q6 Will closing a file descriptor cause it to be removed from all 19 | epoll sets automatically? 20 | 21 | A6 Yes, but be aware of the following point. A file descriptor is a 22 | reference to an open file description (see open(2)). Whenever a 23 | file descriptor is duplicated via dup(2), dup2(2), fcntl(2) 24 | F_DUPFD, or fork(2), a new file descriptor referring to the same 25 | open file description is created. An open file description con‐ 26 | tinues to exist until all file descriptors referring to it have 27 | been closed. A file descriptor is removed from an epoll set only 28 | after all the file descriptors referring to the underlying open 29 | file description have been closed (or before if the file descrip‐ 30 | tor is explicitly removed using epoll_ctl(2) EPOLL_CTL_DEL). 31 | This means that even after a file descriptor that is part of an 32 | epoll set has been closed, events may be reported for that file 33 | descriptor if other file descriptors referring to the same under‐ 34 | lying file description remain open. 35 | 36 | 当调用close()关闭对应的fd时,会使相应的引用计数减一,只有减到0时,epoll才会真的删掉它,所以,比较安全的做法是: 37 | 先del掉它,再close它(如果不确定close是否真的关闭了这个文件。)。 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ubuntu 配置opencv: 52 | vim /etc/ld.so.conf 53 | 加一行include /usr/local/opencv/* 54 | /sbin/ldconfig –v -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/index.html: -------------------------------------------------------------------------------- 1 | Hello World ! -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/threadpool.h: -------------------------------------------------------------------------------- 1 | #ifndef THREADPOOL 2 | #define THREADPOOL 3 | #include "requestData.h" 4 | #include 5 | 6 | const int THREADPOOL_INVALID = -1; 7 | const int THREADPOOL_LOCK_FAILURE = -2; 8 | const int THREADPOOL_QUEUE_FULL = -3; 9 | const int THREADPOOL_SHUTDOWN = -4; 10 | const int THREADPOOL_THREAD_FAILURE = -5; 11 | const int THREADPOOL_GRACEFUL = 1; 12 | 13 | const int MAX_THREADS = 1024; 14 | const int MAX_QUEUE = 65535; 15 | 16 | typedef enum 17 | { 18 | immediate_shutdown = 1, 19 | graceful_shutdown = 2 20 | } threadpool_shutdown_t; 21 | 22 | /** 23 | * @struct threadpool_task 24 | * @brief the work struct 25 | * 26 | * @var function Pointer to the function that will perform the task. 27 | * @var argument Argument to be passed to the function. 28 | */ 29 | 30 | typedef struct { 31 | void (*function)(void *); 32 | void *argument; 33 | } threadpool_task_t; 34 | 35 | /** 36 | * @struct threadpool 37 | * @brief The threadpool struct 38 | * 39 | * @var notify Condition variable to notify worker threads. 40 | * @var threads Array containing worker threads ID. 41 | * @var thread_count Number of threads 42 | * @var queue Array containing the task queue. 43 | * @var queue_size Size of the task queue. 44 | * @var head Index of the first element. 45 | * @var tail Index of the next element. 46 | * @var count Number of pending tasks 47 | * @var shutdown Flag indicating if the pool is shutting down 48 | * @var started Number of started threads 49 | */ 50 | struct threadpool_t 51 | { 52 | pthread_mutex_t lock; 53 | pthread_cond_t notify; 54 | pthread_t *threads; 55 | threadpool_task_t *queue; 56 | int thread_count; 57 | int queue_size; 58 | int head; 59 | int tail; 60 | int count; 61 | int shutdown; 62 | int started; 63 | }; 64 | 65 | threadpool_t *threadpool_create(int thread_count, int queue_size, int flags); 66 | int threadpool_add(threadpool_t *pool, void (*function)(void *), void *argument, int flags); 67 | int threadpool_destroy(threadpool_t *pool, int flags); 68 | int threadpool_free(threadpool_t *pool); 69 | static void *threadpool_thread(void *threadpool); 70 | 71 | #endif -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | ssize_t readn(int fd, void *buff, size_t n) 9 | { 10 | size_t nleft = n; 11 | ssize_t nread = 0; 12 | ssize_t readSum = 0; 13 | char *ptr = (char*)buff; 14 | while (nleft > 0) 15 | { 16 | if ((nread = read(fd, ptr, nleft)) < 0) 17 | { 18 | if (errno == EINTR) 19 | nread = 0; 20 | else if (errno == EAGAIN) 21 | { 22 | return readSum; 23 | } 24 | else 25 | { 26 | return -1; 27 | } 28 | } 29 | else if (nread == 0) 30 | break; 31 | readSum += nread; 32 | nleft -= nread; 33 | ptr += nread; 34 | } 35 | return readSum; 36 | } 37 | 38 | ssize_t writen(int fd, void *buff, size_t n) 39 | { 40 | size_t nleft = n; 41 | ssize_t nwritten = 0; 42 | ssize_t writeSum = 0; 43 | char *ptr = (char*)buff; 44 | while (nleft > 0) 45 | { 46 | if ((nwritten = write(fd, ptr, nleft)) <= 0) 47 | { 48 | if (nwritten < 0) 49 | { 50 | if (errno == EINTR || errno == EAGAIN) 51 | { 52 | nwritten = 0; 53 | continue; 54 | } 55 | else 56 | return -1; 57 | } 58 | } 59 | writeSum += nwritten; 60 | nleft -= nwritten; 61 | ptr += nwritten; 62 | } 63 | return writeSum; 64 | } 65 | 66 | void handle_for_sigpipe() 67 | { 68 | struct sigaction sa; 69 | memset(&sa, '\0', sizeof(sa)); 70 | sa.sa_handler = SIG_IGN; 71 | sa.sa_flags = 0; 72 | if(sigaction(SIGPIPE, &sa, NULL)) 73 | return; 74 | } 75 | 76 | int setSocketNonBlocking(int fd) 77 | { 78 | int flag = fcntl(fd, F_GETFL, 0); 79 | if(flag == -1) 80 | return -1; 81 | 82 | flag |= O_NONBLOCK; 83 | if(fcntl(fd, F_SETFL, flag) == -1) 84 | return -1; 85 | return 0; 86 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.1/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL 2 | #define UTIL 3 | #include 4 | 5 | ssize_t readn(int fd, void *buff, size_t n); 6 | ssize_t writen(int fd, void *buff, size_t n); 7 | void handle_for_sigpipe(); 8 | int setSocketNonBlocking(int fd); 9 | 10 | #endif -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(wildcard *.cpp) 2 | OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE))) 3 | 4 | TARGET := myserver 5 | CC := g++ 6 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui 7 | INCLUDE:= -I./usr/local/include/opencv 8 | CFLAGS := -std=c++11 -g -Wall -O3 $(INCLUDE) 9 | CXXFLAGS:= $(CFLAGS) 10 | 11 | .PHONY : objs clean veryclean rebuild all 12 | all : $(TARGET) 13 | objs : $(OBJS) 14 | rebuild: veryclean all 15 | clean : 16 | rm -fr *.o 17 | veryclean : clean 18 | rm -rf $(TARGET) 19 | 20 | $(TARGET) : $(OBJS) 21 | $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/Makefile1: -------------------------------------------------------------------------------- 1 | cc=g++ -std=c++11 2 | main: main.o requestData.o epoll.o threadpool.o 3 | $(cc) -o main main.o requestData.o epoll.o threadpool.o -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml 4 | main.o: main.cpp 5 | $(cc) -I/usr/local/include/opencv -c main.cpp 6 | requestData.o: requestData.h requestData.cpp 7 | $(cc) -I/usr/local/include/opencv -c requestData.cpp 8 | epoll.o: epoll.h epoll.cpp 9 | $(cc) -I/usr/local/include/opencv -c epoll.cpp 10 | threadpool.o: threadpool.h threadpool.cpp 11 | $(cc) -I/usr/local/include/opencv -c threadpool.cpp 12 | .PHONY: clean 13 | clean: 14 | -rm main *.o 15 | 16 | 17 | 18 | 19 | .PHONY : everything objs clean veryclean rebuild 20 | everything : 21 | $(TARGET) 22 | all : 23 | $(TARGET) 24 | objs : 25 | $(OBJS) 26 | rebuild: 27 | veryclean everything 28 | clean : 29 | rm -fr *.o 30 | veryclean : 31 | clean rm -fr $(TARGET) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/epoll.cpp: -------------------------------------------------------------------------------- 1 | #include "epoll.h" 2 | #include 3 | #include 4 | #include "threadpool.h" 5 | 6 | struct epoll_event* events; 7 | 8 | int epoll_init() 9 | { 10 | int epoll_fd = epoll_create(LISTENQ + 1); 11 | if(epoll_fd == -1) 12 | return -1; 13 | //events = (struct epoll_event*)malloc(sizeof(struct epoll_event) * MAXEVENTS); 14 | events = new epoll_event[MAXEVENTS]; 15 | return epoll_fd; 16 | } 17 | 18 | // 注册新描述符 19 | int epoll_add(int epoll_fd, int fd, void *request, __uint32_t events) 20 | { 21 | struct epoll_event event; 22 | event.data.ptr = request; 23 | event.events = events; 24 | //printf("add to epoll %d\n", fd); 25 | if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event) < 0) 26 | { 27 | perror("epoll_add error"); 28 | return -1; 29 | } 30 | return 0; 31 | } 32 | 33 | // 修改描述符状态 34 | int epoll_mod(int epoll_fd, int fd, void *request, __uint32_t events) 35 | { 36 | struct epoll_event event; 37 | event.data.ptr = request; 38 | event.events = events; 39 | if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &event) < 0) 40 | { 41 | perror("epoll_mod error"); 42 | return -1; 43 | } 44 | return 0; 45 | } 46 | 47 | // 从epoll中删除描述符 48 | int epoll_del(int epoll_fd, int fd, void *request, __uint32_t events) 49 | { 50 | struct epoll_event event; 51 | event.data.ptr = request; 52 | event.events = events; 53 | if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &event) < 0) 54 | { 55 | perror("epoll_del error"); 56 | return -1; 57 | } 58 | return 0; 59 | } 60 | 61 | // 返回活跃事件数 62 | int my_epoll_wait(int epoll_fd, struct epoll_event* events, int max_events, int timeout) 63 | { 64 | int ret_count = epoll_wait(epoll_fd, events, max_events, timeout); 65 | if (ret_count < 0) 66 | { 67 | perror("epoll wait error"); 68 | } 69 | return ret_count; 70 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef EVENTPOLL 3 | #define EVENTPOLL 4 | #include "requestData.h" 5 | 6 | const int MAXEVENTS = 5000; 7 | const int LISTENQ = 1024; 8 | 9 | int epoll_init(); 10 | int epoll_add(int epoll_fd, int fd, void *request, __uint32_t events); 11 | int epoll_mod(int epoll_fd, int fd, void *request, __uint32_t events); 12 | int epoll_del(int epoll_fd, int fd, void *request, __uint32_t events); 13 | int my_epoll_wait(int epoll_fd, struct epoll_event *events, int max_events, int timeout); 14 | 15 | #endif -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/old_version/old_version_0.2/favicon.ico -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/improvement.txt: -------------------------------------------------------------------------------- 1 | 1. 指针可以改成shared_ptr,不需要delete。 2 | 2. 想法在某些地方写成单例模式。 3 | 3. readn 和 writen 改成写到不能写后或读到不能读后加入epoll等待,要记录写到哪或读到哪,维护这样一个状态。比较两者的性能差异。 4 | 4. 信号处理部分可以将 epoll_wait 替换为更安全的 epoll_pwait。 5 | 6 | 7 | 踩坑: 8 | 1. 对EPOLLONESHOT的误解,原以为当epoll_wait监听到相应的事件触发后,epoll会把与事件关联的fd从epoll描述符中禁止掉并且彻底删除,实际上并不会删除,man手册上的解释如下: 9 | EPOLLONESHOT (since Linux 2.6.2) 10 | Sets the one-shot behavior for the associated file descriptor. 11 | This means that after an event is pulled out with 12 | epoll_wait(2) the associated file descriptor is internally 13 | disabled and no other events will be reported by the epoll 14 | interface. The user must call epoll_ctl() with EPOLL_CTL_MOD 15 | to rearm the file descriptor with a new event mask. 16 | 另外: 17 | Linux Programmer's Manual 中第六个问题: 18 | Q6 Will closing a file descriptor cause it to be removed from all 19 | epoll sets automatically? 20 | 21 | A6 Yes, but be aware of the following point. A file descriptor is a 22 | reference to an open file description (see open(2)). Whenever a 23 | file descriptor is duplicated via dup(2), dup2(2), fcntl(2) 24 | F_DUPFD, or fork(2), a new file descriptor referring to the same 25 | open file description is created. An open file description con‐ 26 | tinues to exist until all file descriptors referring to it have 27 | been closed. A file descriptor is removed from an epoll set only 28 | after all the file descriptors referring to the underlying open 29 | file description have been closed (or before if the file descrip‐ 30 | tor is explicitly removed using epoll_ctl(2) EPOLL_CTL_DEL). 31 | This means that even after a file descriptor that is part of an 32 | epoll set has been closed, events may be reported for that file 33 | descriptor if other file descriptors referring to the same under‐ 34 | lying file description remain open. 35 | 36 | 当调用close()关闭对应的fd时,会使相应的引用计数减一,只有减到0时,epoll才会真的删掉它,所以,比较安全的做法是: 37 | 先del掉它,再close它(如果不确定close是否真的关闭了这个文件。)。 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ubuntu 配置opencv: 52 | vim /etc/ld.so.conf 53 | 加一行include /usr/local/opencv/* 54 | /sbin/ldconfig –v -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/index.html: -------------------------------------------------------------------------------- 1 | Hello World ! -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/threadpool.h: -------------------------------------------------------------------------------- 1 | #ifndef THREADPOOL 2 | #define THREADPOOL 3 | #include "requestData.h" 4 | #include 5 | 6 | const int THREADPOOL_INVALID = -1; 7 | const int THREADPOOL_LOCK_FAILURE = -2; 8 | const int THREADPOOL_QUEUE_FULL = -3; 9 | const int THREADPOOL_SHUTDOWN = -4; 10 | const int THREADPOOL_THREAD_FAILURE = -5; 11 | const int THREADPOOL_GRACEFUL = 1; 12 | 13 | const int MAX_THREADS = 1024; 14 | const int MAX_QUEUE = 65535; 15 | 16 | typedef enum 17 | { 18 | immediate_shutdown = 1, 19 | graceful_shutdown = 2 20 | } threadpool_shutdown_t; 21 | 22 | /** 23 | * @struct threadpool_task 24 | * @brief the work struct 25 | * 26 | * @var function Pointer to the function that will perform the task. 27 | * @var argument Argument to be passed to the function. 28 | */ 29 | 30 | typedef struct { 31 | void (*function)(void *); 32 | void *argument; 33 | } threadpool_task_t; 34 | 35 | /** 36 | * @struct threadpool 37 | * @brief The threadpool struct 38 | * 39 | * @var notify Condition variable to notify worker threads. 40 | * @var threads Array containing worker threads ID. 41 | * @var thread_count Number of threads 42 | * @var queue Array containing the task queue. 43 | * @var queue_size Size of the task queue. 44 | * @var head Index of the first element. 45 | * @var tail Index of the next element. 46 | * @var count Number of pending tasks 47 | * @var shutdown Flag indicating if the pool is shutting down 48 | * @var started Number of started threads 49 | */ 50 | struct threadpool_t 51 | { 52 | pthread_mutex_t lock; 53 | pthread_cond_t notify; 54 | pthread_t *threads; 55 | threadpool_task_t *queue; 56 | int thread_count; 57 | int queue_size; 58 | int head; 59 | int tail; 60 | int count; 61 | int shutdown; 62 | int started; 63 | }; 64 | 65 | threadpool_t *threadpool_create(int thread_count, int queue_size, int flags); 66 | int threadpool_add(threadpool_t *pool, void (*function)(void *), void *argument, int flags); 67 | int threadpool_destroy(threadpool_t *pool, int flags); 68 | int threadpool_free(threadpool_t *pool); 69 | static void *threadpool_thread(void *threadpool); 70 | 71 | #endif -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | ssize_t readn(int fd, void *buff, size_t n) 9 | { 10 | size_t nleft = n; 11 | ssize_t nread = 0; 12 | ssize_t readSum = 0; 13 | char *ptr = (char*)buff; 14 | while (nleft > 0) 15 | { 16 | if ((nread = read(fd, ptr, nleft)) < 0) 17 | { 18 | if (errno == EINTR) 19 | nread = 0; 20 | else if (errno == EAGAIN) 21 | { 22 | return readSum; 23 | } 24 | else 25 | { 26 | return -1; 27 | } 28 | } 29 | else if (nread == 0) 30 | break; 31 | readSum += nread; 32 | nleft -= nread; 33 | ptr += nread; 34 | } 35 | return readSum; 36 | } 37 | 38 | ssize_t writen(int fd, void *buff, size_t n) 39 | { 40 | size_t nleft = n; 41 | ssize_t nwritten = 0; 42 | ssize_t writeSum = 0; 43 | char *ptr = (char*)buff; 44 | while (nleft > 0) 45 | { 46 | if ((nwritten = write(fd, ptr, nleft)) <= 0) 47 | { 48 | if (nwritten < 0) 49 | { 50 | if (errno == EINTR || errno == EAGAIN) 51 | { 52 | nwritten = 0; 53 | continue; 54 | } 55 | else 56 | return -1; 57 | } 58 | } 59 | writeSum += nwritten; 60 | nleft -= nwritten; 61 | ptr += nwritten; 62 | } 63 | return writeSum; 64 | } 65 | 66 | void handle_for_sigpipe() 67 | { 68 | struct sigaction sa; 69 | memset(&sa, '\0', sizeof(sa)); 70 | sa.sa_handler = SIG_IGN; 71 | sa.sa_flags = 0; 72 | if(sigaction(SIGPIPE, &sa, NULL)) 73 | return; 74 | } 75 | 76 | int setSocketNonBlocking(int fd) 77 | { 78 | int flag = fcntl(fd, F_GETFL, 0); 79 | if(flag == -1) 80 | return -1; 81 | 82 | flag |= O_NONBLOCK; 83 | if(fcntl(fd, F_SETFL, flag) == -1) 84 | return -1; 85 | return 0; 86 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.2/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL 2 | #define UTIL 3 | #include 4 | 5 | ssize_t readn(int fd, void *buff, size_t n); 6 | ssize_t writen(int fd, void *buff, size_t n); 7 | void handle_for_sigpipe(); 8 | int setSocketNonBlocking(int fd); 9 | 10 | #endif -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(wildcard *.cpp) 2 | OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE))) 3 | 4 | TARGET := myserver 5 | CC := g++ 6 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui 7 | INCLUDE:= -I./usr/local/include/opencv 8 | CFLAGS := -std=c++11 -g -Wall -O3 $(INCLUDE) 9 | CXXFLAGS:= $(CFLAGS) 10 | 11 | .PHONY : objs clean veryclean rebuild all 12 | all : $(TARGET) 13 | objs : $(OBJS) 14 | rebuild: veryclean all 15 | clean : 16 | rm -fr *.o 17 | veryclean : clean 18 | rm -rf $(TARGET) 19 | 20 | $(TARGET) : $(OBJS) 21 | $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/Makefile1: -------------------------------------------------------------------------------- 1 | cc=g++ -std=c++11 2 | main: main.o requestData.o epoll.o threadpool.o 3 | $(cc) -o main main.o requestData.o epoll.o threadpool.o -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml 4 | main.o: main.cpp 5 | $(cc) -I/usr/local/include/opencv -c main.cpp 6 | requestData.o: requestData.h requestData.cpp 7 | $(cc) -I/usr/local/include/opencv -c requestData.cpp 8 | epoll.o: epoll.h epoll.cpp 9 | $(cc) -I/usr/local/include/opencv -c epoll.cpp 10 | threadpool.o: threadpool.h threadpool.cpp 11 | $(cc) -I/usr/local/include/opencv -c threadpool.cpp 12 | .PHONY: clean 13 | clean: 14 | -rm main *.o 15 | 16 | 17 | 18 | 19 | .PHONY : everything objs clean veryclean rebuild 20 | everything : 21 | $(TARGET) 22 | all : 23 | $(TARGET) 24 | objs : 25 | $(OBJS) 26 | rebuild: 27 | veryclean everything 28 | clean : 29 | rm -fr *.o 30 | veryclean : 31 | clean rm -fr $(TARGET) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class Epoll 9 | { 10 | private: 11 | static epoll_event *events; 12 | static std::unordered_map> fd2req; 13 | static int epoll_fd; 14 | static const std::string PATH; 15 | public: 16 | static int epoll_init(int maxevents, int listen_num); 17 | static int epoll_add(int fd, std::shared_ptr request, __uint32_t events); 18 | static int epoll_mod(int fd, std::shared_ptr request, __uint32_t events); 19 | static int epoll_del(int fd, __uint32_t events); 20 | static void my_epoll_wait(int listen_fd, int max_events, int timeout); 21 | static void acceptConnection(int listen_fd, int epoll_fd, const std::string path); 22 | static std::vector> getEventsRequest(int listen_fd, int events_num, const std::string path); 23 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/old_version/old_version_0.3/favicon.ico -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/index.html: -------------------------------------------------------------------------------- 1 | Hello World ! -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/threadpool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | const int THREADPOOL_INVALID = -1; 10 | const int THREADPOOL_LOCK_FAILURE = -2; 11 | const int THREADPOOL_QUEUE_FULL = -3; 12 | const int THREADPOOL_SHUTDOWN = -4; 13 | const int THREADPOOL_THREAD_FAILURE = -5; 14 | const int THREADPOOL_GRACEFUL = 1; 15 | 16 | const int MAX_THREADS = 1024; 17 | const int MAX_QUEUE = 65535; 18 | 19 | typedef enum 20 | { 21 | immediate_shutdown = 1, 22 | graceful_shutdown = 2 23 | } threadpool_shutdown_t; 24 | 25 | struct ThreadPoolTask 26 | { 27 | std::function)> fun; 28 | std::shared_ptr args; 29 | }; 30 | 31 | /** 32 | * @struct threadpool 33 | * @brief The threadpool struct 34 | * 35 | * @var notify Condition variable to notify worker threads. 36 | * @var threads Array containing worker threads ID. 37 | * @var thread_count Number of threads 38 | * @var queue Array containing the task queue. 39 | * @var queue_size Size of the task queue. 40 | * @var head Index of the first element. 41 | * @var tail Index of the next element. 42 | * @var count Number of pending tasks 43 | * @var shutdown Flag indicating if the pool is shutting down 44 | * @var started Number of started threads 45 | */ 46 | void myHandler(std::shared_ptr req); 47 | class ThreadPool 48 | { 49 | private: 50 | static pthread_mutex_t lock; 51 | static pthread_cond_t notify; 52 | static std::vector threads; 53 | static std::vector queue; 54 | static int thread_count; 55 | static int queue_size; 56 | static int head; 57 | // tail 指向尾节点的下一节点 58 | static int tail; 59 | static int count; 60 | static int shutdown; 61 | static int started; 62 | public: 63 | static int threadpool_create(int _thread_count, int _queue_size); 64 | static int threadpool_add(std::shared_ptr args, std::function)> fun = myHandler); 65 | static int threadpool_destroy(); 66 | static int threadpool_free(); 67 | static void *threadpool_thread(void *args); 68 | }; 69 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | ssize_t readn(int fd, void *buff, size_t n) 9 | { 10 | size_t nleft = n; 11 | ssize_t nread = 0; 12 | ssize_t readSum = 0; 13 | char *ptr = (char*)buff; 14 | while (nleft > 0) 15 | { 16 | if ((nread = read(fd, ptr, nleft)) < 0) 17 | { 18 | if (errno == EINTR) 19 | nread = 0; 20 | else if (errno == EAGAIN) 21 | { 22 | return readSum; 23 | } 24 | else 25 | { 26 | return -1; 27 | } 28 | } 29 | else if (nread == 0) 30 | break; 31 | readSum += nread; 32 | nleft -= nread; 33 | ptr += nread; 34 | } 35 | return readSum; 36 | } 37 | 38 | ssize_t writen(int fd, void *buff, size_t n) 39 | { 40 | size_t nleft = n; 41 | ssize_t nwritten = 0; 42 | ssize_t writeSum = 0; 43 | char *ptr = (char*)buff; 44 | while (nleft > 0) 45 | { 46 | if ((nwritten = write(fd, ptr, nleft)) <= 0) 47 | { 48 | if (nwritten < 0) 49 | { 50 | if (errno == EINTR || errno == EAGAIN) 51 | { 52 | nwritten = 0; 53 | continue; 54 | } 55 | else 56 | return -1; 57 | } 58 | } 59 | writeSum += nwritten; 60 | nleft -= nwritten; 61 | ptr += nwritten; 62 | } 63 | return writeSum; 64 | } 65 | 66 | void handle_for_sigpipe() 67 | { 68 | struct sigaction sa; 69 | memset(&sa, '\0', sizeof(sa)); 70 | sa.sa_handler = SIG_IGN; 71 | sa.sa_flags = 0; 72 | if(sigaction(SIGPIPE, &sa, NULL)) 73 | return; 74 | } 75 | 76 | int setSocketNonBlocking(int fd) 77 | { 78 | int flag = fcntl(fd, F_GETFL, 0); 79 | if(flag == -1) 80 | return -1; 81 | 82 | flag |= O_NONBLOCK; 83 | if(fcntl(fd, F_SETFL, flag) == -1) 84 | return -1; 85 | return 0; 86 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.3/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | ssize_t readn(int fd, void *buff, size_t n); 5 | ssize_t writen(int fd, void *buff, size_t n); 6 | void handle_for_sigpipe(); 7 | int setSocketNonBlocking(int fd); -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(wildcard *.cpp) 2 | OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE))) 3 | 4 | TARGET := myserver 5 | CC := g++ 6 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui 7 | INCLUDE:= -I./usr/local/include/opencv 8 | CFLAGS := -std=c++11 -g -Wall -O3 $(INCLUDE) -D_PTHREADS 9 | CXXFLAGS:= $(CFLAGS) 10 | 11 | .PHONY : objs clean veryclean rebuild all 12 | all : $(TARGET) 13 | objs : $(OBJS) 14 | rebuild: veryclean all 15 | clean : 16 | rm -fr *.o 17 | veryclean : clean 18 | rm -rf $(TARGET) 19 | 20 | $(TARGET) : $(OBJS) 21 | $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/Makefile1: -------------------------------------------------------------------------------- 1 | cc=g++ -std=c++11 2 | main: main.o RequestData.o epoll.o threadpool.o 3 | $(cc) -o main main.o RequestData.o epoll.o threadpool.o -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml 4 | main.o: main.cpp 5 | $(cc) -I/usr/local/include/opencv -c main.cpp 6 | RequestData.o: requestData.h RequestData.cpp 7 | $(cc) -I/usr/local/include/opencv -c RequestData.cpp 8 | epoll.o: epoll.h epoll.cpp 9 | $(cc) -I/usr/local/include/opencv -c epoll.cpp 10 | threadpool.o: threadpool.h threadpool.cpp 11 | $(cc) -I/usr/local/include/opencv -c threadpool.cpp 12 | .PHONY: clean 13 | clean: 14 | -rm main *.o 15 | 16 | 17 | 18 | 19 | .PHONY : everything objs clean veryclean rebuild 20 | everything : 21 | $(TARGET) 22 | all : 23 | $(TARGET) 24 | objs : 25 | $(OBJS) 26 | rebuild: 27 | veryclean everything 28 | clean : 29 | rm -fr *.o 30 | veryclean : 31 | clean rm -fr $(TARGET) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/base/mutexLock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "nocopyable.hpp" 3 | #include 4 | #include 5 | 6 | class MutexLock: noncopyable 7 | { 8 | public: 9 | MutexLock() 10 | { 11 | pthread_mutex_init(&mutex, NULL); 12 | } 13 | ~MutexLock() 14 | { 15 | pthread_mutex_lock(&mutex); 16 | pthread_mutex_destroy(&mutex); 17 | } 18 | void lock() 19 | { 20 | pthread_mutex_lock(&mutex); 21 | } 22 | void unlock() 23 | { 24 | pthread_mutex_unlock(&mutex); 25 | } 26 | private: 27 | pthread_mutex_t mutex; 28 | }; 29 | 30 | 31 | class MutexLockGuard: noncopyable 32 | { 33 | public: 34 | explicit MutexLockGuard(MutexLock &_mutex): 35 | mutex(_mutex) 36 | { 37 | mutex.lock(); 38 | } 39 | ~MutexLockGuard() 40 | { 41 | mutex.unlock(); 42 | } 43 | private: 44 | MutexLock &mutex; 45 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/base/nocopyable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class noncopyable 3 | { 4 | protected: 5 | noncopyable() {} 6 | ~noncopyable() {} 7 | private: 8 | noncopyable(const noncopyable&); 9 | const noncopyable& operator=(const noncopyable&); 10 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include "timer.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Epoll 10 | { 11 | public: 12 | typedef std::shared_ptr SP_ReqData; 13 | private: 14 | static epoll_event *events; 15 | static std::unordered_map fd2req; 16 | static int epoll_fd; 17 | static const std::string PATH; 18 | 19 | static TimerManager timer_manager; 20 | public: 21 | static int epoll_init(int maxevents, int listen_num); 22 | static int epoll_add(int fd, SP_ReqData request, __uint32_t events); 23 | static int epoll_mod(int fd, SP_ReqData request, __uint32_t events); 24 | static int epoll_del(int fd, __uint32_t events = (EPOLLIN | EPOLLET | EPOLLONESHOT)); 25 | static void my_epoll_wait(int listen_fd, int max_events, int timeout); 26 | static void acceptConnection(int listen_fd, int epoll_fd, const std::string path); 27 | static std::vector getEventsRequest(int listen_fd, int events_num, const std::string path); 28 | 29 | static void add_timer(SP_ReqData request_data, int timeout); 30 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/old_version/old_version_0.4/favicon.ico -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/index.html: -------------------------------------------------------------------------------- 1 | Hello World ! -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/threadpool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | const int THREADPOOL_INVALID = -1; 10 | const int THREADPOOL_LOCK_FAILURE = -2; 11 | const int THREADPOOL_QUEUE_FULL = -3; 12 | const int THREADPOOL_SHUTDOWN = -4; 13 | const int THREADPOOL_THREAD_FAILURE = -5; 14 | const int THREADPOOL_GRACEFUL = 1; 15 | 16 | const int MAX_THREADS = 1024; 17 | const int MAX_QUEUE = 65535; 18 | 19 | typedef enum 20 | { 21 | immediate_shutdown = 1, 22 | graceful_shutdown = 2 23 | } ShutDownOption; 24 | 25 | struct ThreadPoolTask 26 | { 27 | std::function)> fun; 28 | std::shared_ptr args; 29 | }; 30 | 31 | /** 32 | * @struct threadpool 33 | * @brief The threadpool struct 34 | * 35 | * @var notify Condition variable to notify worker threads. 36 | * @var threads Array containing worker threads ID. 37 | * @var thread_count Number of threads 38 | * @var queue Array containing the task queue. 39 | * @var queue_size Size of the task queue. 40 | * @var head Index of the first element. 41 | * @var tail Index of the next element. 42 | * @var count Number of pending tasks 43 | * @var shutdown Flag indicating if the pool is shutting down 44 | * @var started Number of started threads 45 | */ 46 | void myHandler(std::shared_ptr req); 47 | class ThreadPool 48 | { 49 | private: 50 | static pthread_mutex_t lock; 51 | static pthread_cond_t notify; 52 | static std::vector threads; 53 | static std::vector queue; 54 | static int thread_count; 55 | static int queue_size; 56 | static int head; 57 | // tail 指向尾节点的下一节点 58 | static int tail; 59 | static int count; 60 | static int shutdown; 61 | static int started; 62 | public: 63 | static int threadpool_create(int _thread_count, int _queue_size); 64 | static int threadpool_add(std::shared_ptr args, std::function)> fun = myHandler); 65 | static int threadpool_destroy(ShutDownOption shutdown_option = graceful_shutdown); 66 | static int threadpool_free(); 67 | static void *threadpool_thread(void *args); 68 | }; 69 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include "./base/nocopyable.hpp" 4 | #include "./base/mutexLock.hpp" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class RequestData; 11 | 12 | class TimerNode 13 | { 14 | typedef std::shared_ptr SP_ReqData; 15 | private: 16 | bool deleted; 17 | size_t expired_time; 18 | SP_ReqData request_data; 19 | public: 20 | TimerNode(SP_ReqData _request_data, int timeout); 21 | ~TimerNode(); 22 | void update(int timeout); 23 | bool isvalid(); 24 | void clearReq(); 25 | void setDeleted(); 26 | bool isDeleted() const; 27 | size_t getExpTime() const; 28 | }; 29 | 30 | struct timerCmp 31 | { 32 | bool operator()(std::shared_ptr &a, std::shared_ptr &b) const 33 | { 34 | return a->getExpTime() > b->getExpTime(); 35 | } 36 | }; 37 | 38 | class TimerManager 39 | { 40 | typedef std::shared_ptr SP_ReqData; 41 | typedef std::shared_ptr SP_TimerNode; 42 | private: 43 | std::priority_queue, timerCmp> TimerNodeQueue; 44 | MutexLock lock; 45 | public: 46 | TimerManager(); 47 | ~TimerManager(); 48 | void addTimer(SP_ReqData request_data, int timeout); 49 | void addTimer(SP_TimerNode timer_node); 50 | void handle_expired_event(); 51 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | ssize_t readn(int fd, void *buff, size_t n) 9 | { 10 | size_t nleft = n; 11 | ssize_t nread = 0; 12 | ssize_t readSum = 0; 13 | char *ptr = (char*)buff; 14 | while (nleft > 0) 15 | { 16 | if ((nread = read(fd, ptr, nleft)) < 0) 17 | { 18 | if (errno == EINTR) 19 | nread = 0; 20 | else if (errno == EAGAIN) 21 | { 22 | return readSum; 23 | } 24 | else 25 | { 26 | return -1; 27 | } 28 | } 29 | else if (nread == 0) 30 | break; 31 | readSum += nread; 32 | nleft -= nread; 33 | ptr += nread; 34 | } 35 | return readSum; 36 | } 37 | 38 | ssize_t writen(int fd, void *buff, size_t n) 39 | { 40 | size_t nleft = n; 41 | ssize_t nwritten = 0; 42 | ssize_t writeSum = 0; 43 | char *ptr = (char*)buff; 44 | while (nleft > 0) 45 | { 46 | if ((nwritten = write(fd, ptr, nleft)) <= 0) 47 | { 48 | if (nwritten < 0) 49 | { 50 | if (errno == EINTR || errno == EAGAIN) 51 | { 52 | nwritten = 0; 53 | continue; 54 | } 55 | else 56 | return -1; 57 | } 58 | } 59 | writeSum += nwritten; 60 | nleft -= nwritten; 61 | ptr += nwritten; 62 | } 63 | return writeSum; 64 | } 65 | 66 | void handle_for_sigpipe() 67 | { 68 | struct sigaction sa; 69 | memset(&sa, '\0', sizeof(sa)); 70 | sa.sa_handler = SIG_IGN; 71 | sa.sa_flags = 0; 72 | if(sigaction(SIGPIPE, &sa, NULL)) 73 | return; 74 | } 75 | 76 | int setSocketNonBlocking(int fd) 77 | { 78 | int flag = fcntl(fd, F_GETFL, 0); 79 | if(flag == -1) 80 | return -1; 81 | 82 | flag |= O_NONBLOCK; 83 | if(fcntl(fd, F_SETFL, flag) == -1) 84 | return -1; 85 | return 0; 86 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.4/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | ssize_t readn(int fd, void *buff, size_t n); 5 | ssize_t writen(int fd, void *buff, size_t n); 6 | void handle_for_sigpipe(); 7 | int setSocketNonBlocking(int fd); -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(wildcard *.cpp) 2 | OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE))) 3 | 4 | TARGET := myserver 5 | CC := g++ 6 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui 7 | INCLUDE:= -I./usr/local/include/opencv 8 | CFLAGS := -std=c++11 -g -Wall -O0 $(INCLUDE) -D_PTHREADS 9 | CXXFLAGS:= $(CFLAGS) 10 | 11 | .PHONY : objs clean veryclean rebuild all 12 | all : $(TARGET) 13 | objs : $(OBJS) 14 | rebuild: veryclean all 15 | clean : 16 | rm -fr *.o 17 | veryclean : clean 18 | rm -rf $(TARGET) 19 | 20 | $(TARGET) : $(OBJS) 21 | $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/Makefile1: -------------------------------------------------------------------------------- 1 | cc=g++ -std=c++11 2 | main: main.o RequestData.o epoll.o threadpool.o 3 | $(cc) -o main main.o RequestData.o epoll.o threadpool.o -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml 4 | main.o: main.cpp 5 | $(cc) -I/usr/local/include/opencv -c main.cpp 6 | RequestData.o: requestData.h RequestData.cpp 7 | $(cc) -I/usr/local/include/opencv -c RequestData.cpp 8 | epoll.o: epoll.h epoll.cpp 9 | $(cc) -I/usr/local/include/opencv -c epoll.cpp 10 | threadpool.o: threadpool.h threadpool.cpp 11 | $(cc) -I/usr/local/include/opencv -c threadpool.cpp 12 | .PHONY: clean 13 | clean: 14 | -rm main *.o 15 | 16 | 17 | 18 | 19 | .PHONY : everything objs clean veryclean rebuild 20 | everything : 21 | $(TARGET) 22 | all : 23 | $(TARGET) 24 | objs : 25 | $(OBJS) 26 | rebuild: 27 | veryclean everything 28 | clean : 29 | rm -fr *.o 30 | veryclean : 31 | clean rm -fr $(TARGET) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/base/condition.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "nocopyable.hpp" 3 | #include "mutexLock.hpp" 4 | #include 5 | 6 | class Condition: nocopyable 7 | { 8 | public: 9 | explicit Condition(MutexLock &_mutex): 10 | mutex(_mutex) 11 | { 12 | pthread_cond_init(cond, NULL); 13 | } 14 | ~Condition() 15 | { 16 | pthread_cond_destroy(cond); 17 | } 18 | void wait() 19 | { 20 | pthread_cond_wait(&cond, mutex.get()); 21 | } 22 | void notify() 23 | { 24 | pthread_cond_signal(&cond); 25 | } 26 | void notifyAll() 27 | { 28 | pthread_cond_broadcast(&cond); 29 | } 30 | private: 31 | MutexLock &mutex; 32 | pthread_cond_t cond; 33 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/base/mutexLock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "nocopyable.hpp" 3 | #include 4 | #include 5 | 6 | class MutexLock: noncopyable 7 | { 8 | public: 9 | MutexLock() 10 | { 11 | pthread_mutex_init(&mutex, NULL); 12 | } 13 | ~MutexLock() 14 | { 15 | pthread_mutex_lock(&mutex); 16 | pthread_mutex_destroy(&mutex); 17 | } 18 | void lock() 19 | { 20 | pthread_mutex_lock(&mutex); 21 | } 22 | void unlock() 23 | { 24 | pthread_mutex_unlock(&mutex); 25 | } 26 | pthread_mutex_t *get() 27 | { 28 | return &mutex; 29 | } 30 | private: 31 | pthread_mutex_t mutex; 32 | 33 | // 友元类不受访问权限影响 34 | private: 35 | friend class Condition; 36 | }; 37 | 38 | 39 | class MutexLockGuard: noncopyable 40 | { 41 | public: 42 | explicit MutexLockGuard(MutexLock &_mutex): 43 | mutex(_mutex) 44 | { 45 | mutex.lock(); 46 | } 47 | ~MutexLockGuard() 48 | { 49 | mutex.unlock(); 50 | } 51 | private: 52 | MutexLock &mutex; 53 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/base/nocopyable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class noncopyable 3 | { 4 | protected: 5 | noncopyable() {} 6 | ~noncopyable() {} 7 | private: 8 | noncopyable(const noncopyable&); 9 | const noncopyable& operator=(const noncopyable&); 10 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include "timer.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Epoll 10 | { 11 | public: 12 | typedef std::shared_ptr SP_ReqData; 13 | private: 14 | static const int MAXFDS = 1000; 15 | static epoll_event *events; 16 | static SP_ReqData fd2req[MAXFDS]; 17 | static int epoll_fd; 18 | static const std::string PATH; 19 | 20 | static TimerManager timer_manager; 21 | public: 22 | static int epoll_init(int maxevents, int listen_num); 23 | static int epoll_add(int fd, SP_ReqData request, __uint32_t events); 24 | static int epoll_mod(int fd, SP_ReqData request, __uint32_t events); 25 | static int epoll_del(int fd, __uint32_t events = (EPOLLIN | EPOLLET | EPOLLONESHOT)); 26 | static void my_epoll_wait(int listen_fd, int max_events, int timeout); 27 | static void acceptConnection(int listen_fd, int epoll_fd, const std::string path); 28 | static std::vector getEventsRequest(int listen_fd, int events_num, const std::string path); 29 | 30 | static void add_timer(SP_ReqData request_data, int timeout); 31 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/old_version/old_version_0.5/favicon.ico -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/index.html: -------------------------------------------------------------------------------- 1 | Hello World ! -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/threadpool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | //#include "condition.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | const int THREADPOOL_INVALID = -1; 10 | const int THREADPOOL_LOCK_FAILURE = -2; 11 | const int THREADPOOL_QUEUE_FULL = -3; 12 | const int THREADPOOL_SHUTDOWN = -4; 13 | const int THREADPOOL_THREAD_FAILURE = -5; 14 | const int THREADPOOL_GRACEFUL = 1; 15 | 16 | const int MAX_THREADS = 1024; 17 | const int MAX_QUEUE = 65535; 18 | 19 | typedef enum 20 | { 21 | immediate_shutdown = 1, 22 | graceful_shutdown = 2 23 | } ShutDownOption; 24 | 25 | struct ThreadPoolTask 26 | { 27 | std::function)> fun; 28 | std::shared_ptr args; 29 | }; 30 | 31 | void myHandler(std::shared_ptr req); 32 | 33 | class ThreadPool 34 | { 35 | private: 36 | static pthread_mutex_t lock; 37 | static pthread_cond_t notify; 38 | 39 | static std::vector threads; 40 | static std::vector queue; 41 | static int thread_count; 42 | static int queue_size; 43 | static int head; 44 | // tail 指向尾节点的下一节点 45 | static int tail; 46 | static int count; 47 | static int shutdown; 48 | static int started; 49 | public: 50 | static int threadpool_create(int _thread_count, int _queue_size); 51 | static int threadpool_add(std::shared_ptr args, std::function)> fun = myHandler); 52 | static int threadpool_destroy(ShutDownOption shutdown_option = graceful_shutdown); 53 | static int threadpool_free(); 54 | static void *threadpool_thread(void *args); 55 | }; 56 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include "./base/nocopyable.hpp" 4 | #include "./base/mutexLock.hpp" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class RequestData; 11 | 12 | class TimerNode 13 | { 14 | typedef std::shared_ptr SP_ReqData; 15 | private: 16 | bool deleted; 17 | size_t expired_time; 18 | SP_ReqData request_data; 19 | public: 20 | TimerNode(SP_ReqData _request_data, int timeout); 21 | ~TimerNode(); 22 | void update(int timeout); 23 | bool isvalid(); 24 | void clearReq(); 25 | void setDeleted(); 26 | bool isDeleted() const; 27 | size_t getExpTime() const; 28 | }; 29 | 30 | struct timerCmp 31 | { 32 | bool operator()(std::shared_ptr &a, std::shared_ptr &b) const 33 | { 34 | return a->getExpTime() > b->getExpTime(); 35 | } 36 | }; 37 | 38 | class TimerManager 39 | { 40 | typedef std::shared_ptr SP_ReqData; 41 | typedef std::shared_ptr SP_TimerNode; 42 | private: 43 | std::priority_queue, timerCmp> TimerNodeQueue; 44 | MutexLock lock; 45 | public: 46 | TimerManager(); 47 | ~TimerManager(); 48 | void addTimer(SP_ReqData request_data, int timeout); 49 | void addTimer(SP_TimerNode timer_node); 50 | void handle_expired_event(); 51 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.5/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | ssize_t readn(int fd, void *buff, size_t n); 6 | ssize_t readn(int fd, std::string &inBuffer); 7 | ssize_t writen(int fd, void *buff, size_t n); 8 | ssize_t writen(int fd, std::string &sbuff); 9 | void handle_for_sigpipe(); 10 | int setSocketNonBlocking(int fd); -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/AsyncLogging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CountDownLatch.h" 4 | #include "MutexLock.h" 5 | #include "Thread.h" 6 | #include "LogStream.h" 7 | #include "noncopyable.h" 8 | #include 9 | #include 10 | #include 11 | 12 | // extern const int kSmallBuffer; 13 | // extern const int kLargeBuffer; 14 | 15 | // template class FixedBuffer; 16 | // template class FixedBuffer; 17 | 18 | class AsyncLogging : noncopyable 19 | { 20 | public: 21 | 22 | AsyncLogging(const std::string basename, int flushInterval = 2); 23 | 24 | ~AsyncLogging() 25 | { 26 | if (running_) 27 | { 28 | stop(); 29 | } 30 | } 31 | 32 | void append(const char* logline, int len); 33 | 34 | void start() 35 | { 36 | running_ = true; 37 | thread_.start(); 38 | latch_.wait(); 39 | } 40 | 41 | void stop() 42 | { 43 | running_ = false; 44 | cond_.notify(); 45 | thread_.join(); 46 | } 47 | 48 | private: 49 | 50 | // declare but not define, prevent compiler-synthesized functions 51 | AsyncLogging(const AsyncLogging&); // ptr_container 52 | void operator=(const AsyncLogging&); // ptr_container 53 | 54 | void threadFunc(); 55 | 56 | typedef FixedBuffer Buffer; 57 | typedef std::vector> BufferVector; 58 | typedef std::shared_ptr BufferPtr; 59 | 60 | const int flushInterval_; 61 | bool running_; 62 | std::string basename_; 63 | Thread thread_; 64 | MutexLock mutex_; 65 | Condition cond_; 66 | BufferPtr currentBuffer_; 67 | BufferPtr nextBuffer_; 68 | BufferVector buffers_; 69 | CountDownLatch latch_; 70 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/Condition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "noncopyable.h" 3 | #include "MutexLock.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class Condition: noncopyable 11 | { 12 | public: 13 | explicit Condition(MutexLock &_mutex): 14 | mutex(_mutex) 15 | { 16 | pthread_cond_init(&cond, NULL); 17 | } 18 | ~Condition() 19 | { 20 | pthread_cond_destroy(&cond); 21 | } 22 | void wait() 23 | { 24 | pthread_cond_wait(&cond, mutex.get()); 25 | } 26 | void notify() 27 | { 28 | pthread_cond_signal(&cond); 29 | } 30 | void notifyAll() 31 | { 32 | pthread_cond_broadcast(&cond); 33 | } 34 | bool waitForSeconds(int seconds) 35 | { 36 | struct timespec abstime; 37 | clock_gettime(CLOCK_REALTIME, &abstime); 38 | abstime.tv_sec += static_cast(seconds); 39 | return ETIMEDOUT == pthread_cond_timedwait(&cond, mutex.get(), &abstime); 40 | } 41 | private: 42 | MutexLock &mutex; 43 | pthread_cond_t cond; 44 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/CountDownLatch.cpp: -------------------------------------------------------------------------------- 1 | #include "CountDownLatch.h" 2 | 3 | 4 | CountDownLatch::CountDownLatch(int count) 5 | : mutex_(), 6 | condition_(mutex_), 7 | count_(count) 8 | { 9 | } 10 | 11 | void CountDownLatch::wait() 12 | { 13 | MutexLockGuard lock(mutex_); 14 | while (count_ > 0) 15 | { 16 | condition_.wait(); 17 | } 18 | } 19 | 20 | void CountDownLatch::countDown() 21 | { 22 | MutexLockGuard lock(mutex_); 23 | --count_; 24 | if (count_ == 0) 25 | { 26 | condition_.notifyAll(); 27 | } 28 | } 29 | 30 | int CountDownLatch::getCount() const 31 | { 32 | MutexLockGuard lock(mutex_); 33 | return count_; 34 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Condition.h" 4 | #include "MutexLock.h" 5 | 6 | #include "noncopyable.h" 7 | 8 | class CountDownLatch : noncopyable 9 | { 10 | public: 11 | explicit CountDownLatch(int count); 12 | void wait(); 13 | void countDown(); 14 | int getCount() const; 15 | 16 | private: 17 | mutable MutexLock mutex_; 18 | Condition condition_; 19 | int count_; 20 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/CurrentThread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /* 5 | namespace CurrendThread 6 | { 7 | // internal 8 | extern __thread int t_cachedTid; 9 | extern __thread char t_tidString[32]; 10 | extern __thread int t_tidStringLength; 11 | extern __thread const char* t_threadName; 12 | void cacheTid(); 13 | inline int tid() 14 | { 15 | if (__builtin_expect(t_cachedTid == 0, 0)) 16 | { 17 | cacheTid(); 18 | } 19 | return t_cachedTid; 20 | } 21 | 22 | inline const char* tidString() // for logging 23 | { 24 | return t_tidString; 25 | } 26 | 27 | inline int tidStringLength() // for logging 28 | { 29 | return t_tidStringLength; 30 | } 31 | 32 | inline const char* name() 33 | { 34 | return t_threadName; 35 | } 36 | } 37 | */ 38 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/FileUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "FileUtil.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | AppendFile::AppendFile(string filename) 12 | : fp_(fopen(filename.c_str(), "ae")) 13 | { 14 | setbuffer(fp_, buffer_, sizeof buffer_); 15 | } 16 | 17 | AppendFile::~AppendFile() 18 | { 19 | fclose(fp_); 20 | } 21 | 22 | void AppendFile::append(const char* logline, const size_t len) 23 | { 24 | size_t n = write(logline, len); 25 | size_t remain = len - n; 26 | while (remain > 0) 27 | { 28 | size_t x = write(logline + n, remain); 29 | if (x == 0) 30 | { 31 | int err = ferror(fp_); 32 | if (err) 33 | { 34 | fprintf(stderr, "AppendFile::append() failed !\n"); 35 | } 36 | break; 37 | } 38 | n += x; 39 | remain = len - n; 40 | } 41 | } 42 | 43 | void AppendFile::flush() 44 | { 45 | fflush(fp_); 46 | } 47 | 48 | size_t AppendFile::write(const char* logline, size_t len) 49 | { 50 | // #undef fwrite_unlocked 51 | return ::fwrite_unlocked(logline, 1, len, fp_); 52 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/FileUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "noncopyable.h" 4 | #include 5 | 6 | class AppendFile : noncopyable 7 | { 8 | public: 9 | explicit AppendFile(std::string filename); 10 | ~AppendFile(); 11 | void append(const char* logline, const size_t len); 12 | void flush(); 13 | 14 | private: 15 | size_t write(const char* logline, size_t len); 16 | FILE* fp_; 17 | char buffer_[64*1024]; 18 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/LogFile.cpp: -------------------------------------------------------------------------------- 1 | #include "LogFile.h" 2 | 3 | #include "FileUtil.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | // "/logfile.log" 11 | LogFile::LogFile(const string& basename, int flushEveryN) 12 | : basename_(basename), 13 | flushEveryN_(flushEveryN), 14 | count_(0), 15 | mutex_(new MutexLock) 16 | { 17 | //assert(basename.find('/') >= 0); 18 | file_.reset(new AppendFile(basename)); 19 | } 20 | 21 | LogFile::~LogFile() 22 | { 23 | } 24 | 25 | void LogFile::append(const char* logline, int len) 26 | { 27 | MutexLockGuard lock(*mutex_); 28 | append_unlocked(logline, len); 29 | } 30 | 31 | void LogFile::flush() 32 | { 33 | MutexLockGuard lock(*mutex_); 34 | file_->flush(); 35 | } 36 | 37 | void LogFile::append_unlocked(const char* logline, int len) 38 | { 39 | file_->append(logline, len); 40 | ++count_; 41 | if (count_ >= flushEveryN_) 42 | { 43 | count_ = 0; 44 | file_->flush(); 45 | } 46 | } -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/LogFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FileUtil.h" 3 | #include "MutexLock.h" 4 | #include "noncopyable.h" 5 | #include 6 | #include 7 | 8 | class LogFile : noncopyable 9 | { 10 | public: 11 | LogFile(const std::string& basename, int flushEveryN = 1024); 12 | ~LogFile(); 13 | 14 | void append(const char* logline, int len); 15 | void flush(); 16 | bool rollFile(); 17 | 18 | private: 19 | void append_unlocked(const char* logline, int len); 20 | 21 | const std::string basename_; 22 | const int flushEveryN_; 23 | 24 | int count_; 25 | std::unique_ptr mutex_; 26 | std::unique_ptr file_; 27 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/Logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "LogStream.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class AsyncLogging; 9 | 10 | class Logger 11 | { 12 | public: 13 | ~Logger(); 14 | Logger(const char *fileName, int line); 15 | LogStream& stream() { return impl_.stream_; } 16 | 17 | private: 18 | class Impl 19 | { 20 | public: 21 | Impl(const char *fileName, int line); 22 | void formatTime(); 23 | 24 | LogStream stream_; 25 | int line_; 26 | std::string basename_; 27 | }; 28 | Impl impl_; 29 | }; 30 | 31 | #define LOG Logger(__FILE__, __LINE__).stream() -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE := $(wildcard *.cpp) 2 | OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE))) 3 | 4 | TARGET := myserver 5 | CC := g++ 6 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui 7 | INCLUDE:= -I./usr/local/include/opencv 8 | CFLAGS := -std=c++11 -g -Wall -O0 $(INCLUDE) -D_PTHREADS 9 | CXXFLAGS:= $(CFLAGS) 10 | 11 | .PHONY : objs clean veryclean rebuild all 12 | all : $(TARGET) 13 | objs : $(OBJS) 14 | rebuild: veryclean all 15 | clean : 16 | rm -fr *.o 17 | veryclean : clean 18 | rm -rf $(TARGET) 19 | 20 | $(TARGET) : $(OBJS) 21 | $(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/Makefile1: -------------------------------------------------------------------------------- 1 | cc=g++ -std=c++11 2 | main: main.o RequestData.o epoll.o threadpool.o 3 | $(cc) -o main main.o RequestData.o epoll.o threadpool.o -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml 4 | main.o: main.cpp 5 | $(cc) -I/usr/local/include/opencv -c main.cpp 6 | RequestData.o: requestData.h RequestData.cpp 7 | $(cc) -I/usr/local/include/opencv -c RequestData.cpp 8 | epoll.o: epoll.h epoll.cpp 9 | $(cc) -I/usr/local/include/opencv -c epoll.cpp 10 | threadpool.o: threadpool.h threadpool.cpp 11 | $(cc) -I/usr/local/include/opencv -c threadpool.cpp 12 | .PHONY: clean 13 | clean: 14 | -rm main *.o 15 | 16 | 17 | 18 | 19 | .PHONY : everything objs clean veryclean rebuild 20 | everything : 21 | $(TARGET) 22 | all : 23 | $(TARGET) 24 | objs : 25 | $(OBJS) 26 | rebuild: 27 | veryclean everything 28 | clean : 29 | rm -fr *.o 30 | veryclean : 31 | clean rm -fr $(TARGET) -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/MutexLock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "noncopyable.h" 3 | #include 4 | #include 5 | 6 | class MutexLock: noncopyable 7 | { 8 | public: 9 | MutexLock() 10 | { 11 | pthread_mutex_init(&mutex, NULL); 12 | } 13 | ~MutexLock() 14 | { 15 | pthread_mutex_lock(&mutex); 16 | pthread_mutex_destroy(&mutex); 17 | } 18 | void lock() 19 | { 20 | pthread_mutex_lock(&mutex); 21 | } 22 | void unlock() 23 | { 24 | pthread_mutex_unlock(&mutex); 25 | } 26 | pthread_mutex_t *get() 27 | { 28 | return &mutex; 29 | } 30 | private: 31 | pthread_mutex_t mutex; 32 | 33 | // 友元类不受访问权限影响 34 | private: 35 | friend class Condition; 36 | }; 37 | 38 | 39 | class MutexLockGuard: noncopyable 40 | { 41 | public: 42 | explicit MutexLockGuard(MutexLock &_mutex): 43 | mutex(_mutex) 44 | { 45 | mutex.lock(); 46 | } 47 | ~MutexLockGuard() 48 | { 49 | mutex.unlock(); 50 | } 51 | private: 52 | MutexLock &mutex; 53 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/Thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CountDownLatch.h" 4 | #include 5 | #include "noncopyable.h" 6 | #include 7 | #include 8 | #include 9 | 10 | class Thread : noncopyable 11 | { 12 | public: 13 | typedef std::function ThreadFunc; 14 | 15 | explicit Thread(const ThreadFunc&, const std::string& name = std::string()); 16 | ~Thread(); 17 | 18 | void start(); 19 | int join(); 20 | 21 | bool started() const { return started_; } 22 | pid_t tid() const { return tid_; } 23 | const std::string& name() const { return name_; } 24 | 25 | 26 | private: 27 | void setDefaultName(); 28 | 29 | bool started_; 30 | bool joined_; 31 | pthread_t pthreadId_; 32 | pid_t tid_; 33 | ThreadFunc func_; 34 | std::string name_; 35 | CountDownLatch latch_; 36 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/epoll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include "timer.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Epoll 10 | { 11 | public: 12 | typedef std::shared_ptr SP_ReqData; 13 | private: 14 | static const int MAXFDS = 1000; 15 | static epoll_event *events; 16 | static SP_ReqData fd2req[MAXFDS]; 17 | static int epoll_fd; 18 | static const std::string PATH; 19 | 20 | static TimerManager timer_manager; 21 | public: 22 | static int epoll_init(int maxevents, int listen_num); 23 | static int epoll_add(int fd, SP_ReqData request, __uint32_t events); 24 | static int epoll_mod(int fd, SP_ReqData request, __uint32_t events); 25 | static int epoll_del(int fd, __uint32_t events = (EPOLLIN | EPOLLET | EPOLLONESHOT)); 26 | static void my_epoll_wait(int listen_fd, int max_events, int timeout); 27 | static void acceptConnection(int listen_fd, int epoll_fd, const std::string path); 28 | static std::vector getEventsRequest(int listen_fd, int events_num, const std::string path); 29 | 30 | static void add_timer(SP_ReqData request_data, int timeout); 31 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hansimov/linux-server/5380d749b31b2652faf06c2b612dabc070856d4e/WebServerCpp11/old_version/old_version_0.6/favicon.ico -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/index.html: -------------------------------------------------------------------------------- 1 | Hello World ! -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/noncopyable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class noncopyable 3 | { 4 | protected: 5 | noncopyable() {} 6 | ~noncopyable() {} 7 | private: 8 | noncopyable(const noncopyable&); 9 | const noncopyable& operator=(const noncopyable&); 10 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/threadpool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | //#include "Condition.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | const int THREADPOOL_INVALID = -1; 10 | const int THREADPOOL_LOCK_FAILURE = -2; 11 | const int THREADPOOL_QUEUE_FULL = -3; 12 | const int THREADPOOL_SHUTDOWN = -4; 13 | const int THREADPOOL_THREAD_FAILURE = -5; 14 | const int THREADPOOL_GRACEFUL = 1; 15 | 16 | const int MAX_THREADS = 1024; 17 | const int MAX_QUEUE = 65535; 18 | 19 | typedef enum 20 | { 21 | immediate_shutdown = 1, 22 | graceful_shutdown = 2 23 | } ShutDownOption; 24 | 25 | struct ThreadPoolTask 26 | { 27 | std::function)> fun; 28 | std::shared_ptr args; 29 | }; 30 | 31 | void myHandler(std::shared_ptr req); 32 | 33 | class ThreadPool 34 | { 35 | private: 36 | static pthread_mutex_t lock; 37 | static pthread_cond_t notify; 38 | 39 | static std::vector threads; 40 | static std::vector queue; 41 | static int thread_count; 42 | static int queue_size; 43 | static int head; 44 | // tail 指向尾节点的下一节点 45 | static int tail; 46 | static int count; 47 | static int shutdown; 48 | static int started; 49 | public: 50 | static int threadpool_create(int _thread_count, int _queue_size); 51 | static int threadpool_add(std::shared_ptr args, std::function)> fun = myHandler); 52 | static int threadpool_destroy(ShutDownOption shutdown_option = graceful_shutdown); 53 | static int threadpool_free(); 54 | static void *threadpool_thread(void *args); 55 | }; 56 | -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "requestData.h" 3 | #include "noncopyable.h" 4 | #include "MutexLock.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class RequestData; 11 | 12 | class TimerNode 13 | { 14 | typedef std::shared_ptr SP_ReqData; 15 | private: 16 | bool deleted; 17 | size_t expired_time; 18 | SP_ReqData request_data; 19 | public: 20 | TimerNode(SP_ReqData _request_data, int timeout); 21 | ~TimerNode(); 22 | void update(int timeout); 23 | bool isvalid(); 24 | void clearReq(); 25 | void setDeleted(); 26 | bool isDeleted() const; 27 | size_t getExpTime() const; 28 | }; 29 | 30 | struct timerCmp 31 | { 32 | bool operator()(std::shared_ptr &a, std::shared_ptr &b) const 33 | { 34 | return a->getExpTime() > b->getExpTime(); 35 | } 36 | }; 37 | 38 | class TimerManager 39 | { 40 | typedef std::shared_ptr SP_ReqData; 41 | typedef std::shared_ptr SP_TimerNode; 42 | private: 43 | std::priority_queue, timerCmp> TimerNodeQueue; 44 | MutexLock lock; 45 | public: 46 | TimerManager(); 47 | ~TimerManager(); 48 | void addTimer(SP_ReqData request_data, int timeout); 49 | void addTimer(SP_TimerNode timer_node); 50 | void handle_expired_event(); 51 | }; -------------------------------------------------------------------------------- /WebServerCpp11/old_version/old_version_0.6/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | ssize_t readn(int fd, void *buff, size_t n); 6 | ssize_t readn(int fd, std::string &inBuffer); 7 | ssize_t writen(int fd, void *buff, size_t n); 8 | ssize_t writen(int fd, std::string &sbuff); 9 | void handle_for_sigpipe(); 10 | int setSocketNonBlocking(int fd); -------------------------------------------------------------------------------- /WebServerCpp11/测试及改进.md: -------------------------------------------------------------------------------- 1 | # 测试及改进 2 | 3 | ## 测试环境 4 | * OS:Ubuntu 14.04 5 | * 内存:8G 6 | * CPU:I7-4720HQ 7 | 8 | ## 测试方法 9 | * 理想的测试环境是两台计算机,带宽无限,现在的网卡虽然都是千兆网卡,但是普通家用的网线都是5类双绞线,最高100Mbps,在linux下用ethtool可以看到网卡的速度被限制为100Mbsp,无法更改为更高的,经测试很容易跑满带宽,因此退而选择本地环境。 10 | * 使用工具Webbench,开启1000客户端进程,时间为60s 11 | * 分别测试短连接和长连接的情况 12 | * 关闭所有的输出及Log 13 | * 为避免磁盘IO对测试结果的影响,测试响应为内存中的"Hello World"字符加上必要的HTTP头 14 | * 我的最终版本中很多方面借鉴了muduo的思路,muduo中也提供了一个简单的HTTP echo测试,因此我将与muduo进行一个小小的对比,我修改了muduo测试的代码,使其echo相同的内容,关闭muduo的所有输出及Log 15 | * 线程池开启4线程 16 | * 因为发送的内容很少,为避免发送可能的延迟,关闭Nagle算法 17 | 18 | 19 | ## 测试结果及分析 20 | 测试截图放在最后 21 | 22 | | 服务器 | 短连接QPS | 长连接QPS | 23 | | - | :-: | -: | 24 | | WebServer | 126798| 335338 | 25 | | Muduo | 88430 | 358302 | 26 | 27 | * 首先很明显的一点是长链接能处理的请求数是短连接的三四倍,因为没有了连接建立和断开的开销,不需要频繁accept和shutdown\close等系统调用,也不需要频繁建立和销毁对应的结构体。 28 | * 我的服务器在最后的版本中,没有改进输入输出Buffer,用了效率低下的string,muduo用的是设计良好的vector,我将在后续改进这一点。这也造成了在长连接的情况下,我的server逊于muduo。虽说边沿触发效率高一点,但是还是比不过在Buffer上性能的优化的。 29 | * 短链接的情况下,我的服务器要超过Muduo很多。原因在于:Muduo采用水平触发方式(Linux下用epoll),并且做法是每次Acceptor只accept一次就返回,面对突然的并发量,必然会因为频繁的epoll_wait耽误大量的时间,而我的做法是用while包裹accept,一直accept到不能再accept。当然,如果同时连接的请求很少,陈硕在书中也提到过,假如一次只有一个连接,那么我的方式就会多一次accpet才能跳出循环,但是这样的代价似乎微不足道啊,换来的效率却高了不少。 30 | * 空闲时,Server几乎不占CPU,短连接时,各线程的CPU负载比较均衡,长连接时,主线程负载0,线程池的线程负载接近100%,因为没有新的连接需要处理。各种情况均正常。 31 | * 没有严格的考证,测试时发现,HTTP的header解析的结果用map比用unordered_map快,网上的博客里有很多人做了测试,我在做实验的时候大致也发现了。主要是因为数据量太小,一个HTTP请求头才几个头部字段,建立unordered_map的成本要比map高,数据量小,复杂度根本体现不出来。 32 | 33 | 34 | 35 | ## 测试结果截图 36 | * WebServer短连接测试 37 | ![shortWeb](https://github.com/linyacool/WebServer/blob/master/datum/WebServer.png) 38 | * muduo短连接测试 39 | ![shortMuduo](https://github.com/linyacool/WebServer/blob/master/datum/muduo.png) 40 | * WebServer长连接测试 41 | ![keepWeb](https://github.com/linyacool/WebServer/blob/master/datum/WebServerk.png) 42 | * muduo长连接测试 43 | ![keepMuduo](https://github.com/linyacool/WebServer/blob/master/datum/muduok.png) 44 | * WebServer空闲负载 45 | ![idle](https://github.com/linyacool/WebServer/blob/master/datum/idle.png) 46 | * WebServer短连接CPU负载 47 | ![short](https://github.com/linyacool/WebServer/blob/master/datum/close.png) 48 | * WebServer长连接CPU负载 49 | ![keep](https://github.com/linyacool/WebServer/blob/master/datum/keepalive.png) 50 | 51 | -------------------------------------------------------------------------------- /WebServerCpp11/版本历史.md: -------------------------------------------------------------------------------- 1 | # 版本历史 2 | 从0.1最初形成到一点一点改进到0.6,到最终看了muduo,痛下决心重写,最终的版本完全从头再来了,但有了前面的经验,写起来顺畅了不少,但花了比之前所有加起来还要长的时间 3 | ## 0.1 4 | 5 | 第一版是看了很多Github上别人写的服务器,以及博客上的一些总结,结合自己的理解写出来的。模型结构如下: 6 | 7 | * 使用了epoll边沿触发+EPOLLONESHOT+非阻塞IO 8 | * 使用了一个固定线程数的线程池 9 | * 实现了一个任务队列,由条件变量触发通知新任务的到来 10 | * 实现了一个小根堆的定时器及时剔除超时请求,使用了STL的优先队列来管理定时器 11 | * 解析了HTTP的get、post请求,支持长短连接 12 | * mime设计为单例模式 13 | * 线程的工作分配为: 14 | * 主线程负责等待epoll中的事件,并把到来的事件放进任务队列,在每次循环的结束剔除超时请求和被置为删除的时间结点 15 | * 工作线程阻塞在条件变量的等待中,新任务到来后,某一工作线程会被唤醒,执行具体的IO操作和计算任务,如果需要继续监听,会添加到epoll中 16 | 17 | * 锁的使用有两处: 18 | * 第一处是任务队列的添加和取操作,都需要加锁,并配合条件变量,跨越了多个线程。 19 | * 第二处是定时器结点的添加和删除,需要加锁,主线程和工作线程都要操作定时器队列。 20 | 21 | 22 | 23 | 第一版的服务器已经相对较完整了,该有的功能都已经具备了 24 | 25 | ## 0.2 26 | 27 | 在第一版的基础上,优化了代码结构,自己设计了RAII锁机制,使锁能够自动释放,并修复了一些小的bug 28 | 29 | ## 0.3 30 | 31 | * 几乎全部的裸指针被智能指针替代 32 | * 利用weak_ptr解决时间结点和HTTP类互指的问题 33 | * 任务队列的任务结构从函数指针+参数指针转换为C++11的function 34 | 35 | 这一版还是花了不少时间的,毕竟对象的生命周期不由自己控制了 36 | 37 | ## 0.4 38 | 39 | 这个时候买了陈硕的《Linux多线程服务端编程》书,看了一部分,从前面几章获得启发 40 | * 为不提供拷贝构造和赋值运算符的类添加了noncopyable基类 41 | * 重写了RAII机制的锁,学习muduo中的做法 42 | * 重写了单例模式,将双重加锁改为更简单而安全的pthread_once() 43 | 44 | ## 0.5 45 | 46 | * 修复了一些bug,稍微调整了类的结构 47 | * 封装了条件变量 48 | 49 | ## 0.6 50 | 51 | * 仿照muduo,写了4个缓冲区的异步Log日志,没有区分优先级,其它基本都具备了 52 | 53 | ## WebServer(重构) 54 | 55 | 不知道该给自己的服务器取什么名字好,随便叫个吧……最后一版被我改的面目全非,也是下了很大的决心。之前的版本无非修修补补,算是自我检讨的过程,但是闭门造车并不可取,于是我把陈硕的《Linux多线程服务端编程》看完了,书上虽然贴了部分源码,但我看的还是朦朦胧胧,很多地方不明白,花了几天时间把源码看了,不懂的地方再回过来看书,总算是弄明白了。看了大牛的代码,再看自己的……哎我重写总行了吧 56 | 57 | 顺便吐槽一下自己,之前在知乎上看到陈硕一直推销自己的书,我还觉得这人好功利,后来被师兄推荐,看了一下目录,觉得可以参考一下就买了。没想到书就一点一点这么看完了……还看了好几遍,源码也是看了好几遍…… 58 | 59 | 当然,这不是最终篇,可改进的地方还有很多,绝对不敢说看了几本书就敢说自己写的东西比大牛写的好,我还会继续改进自己的server的 60 | 61 | 最后版本的东西没有在这里介绍,写在了模型结构里,这里只想写一下自己的心路历程,记录一下小白成长之路~ -------------------------------------------------------------------------------- /WebServerCpp11/连接的维护.md: -------------------------------------------------------------------------------- 1 | # 连接维护(针对非阻塞IO) 2 | 3 | ### 建立连接 4 | 5 | * 建立连接的过程 6 | 连接的建立比较简单,server端通过socket(),bind(),listen(),并使用epoll ET模式监听listenfd的读请求,当TCP连接完成3次握手后,会触发listenfd的读事件,应用程序调用accept(),会检查已完成的连接队列,如果队列里有连接,就返回这个连接,出错或连接为空时返回-1。此时,已经可以进行正常的读写操作了。 当然,因为是ET模式,accept()要一直循环到就绪连接为空。 7 | * 分析 8 | 之所以说建立连接的过程比较简单,是因为数据的通信已经由操作系统帮我们完成了,这里的通信是指3次握手的过程,这个过程不需要应用程序参与,当应用程序感知到连接时,此时该连接已经完成了3次握手的过程,accept就好了。另一个原因是一般情况下,连接的建立都是client发起的,server端被动建立连接就好了,也不会出现同时建立的情况。 9 | * 限制 10 | 假设server只监听一个端口,一个连接就是一个四元组(原ip,原port,对端ip, 对端port),那么理论上可以建立2^48个连接,可是,fd可没有这么多(操作系统限制、用户进程限制)。当连接满了,如果空等而不连接,那么就绪队列也满了后,会导致新连接无法建立。这里的做法我参考了muduo,准备一个空的文件描述符,accept()后直接close(),这样对端不会收到RST,至少可以知道服务器正在运行。 11 | 12 | ### 关闭连接 13 | 14 | 相对于连接的建立,关闭连接则复杂的多,远不是一个close()那么简单,关闭连接要优雅。 15 | 16 | ##### 什么时候关闭连接? 17 | 通常server和client都可以主动发Fin来关闭连接 18 | 19 | * 对于client(非Keep-Alive),发送完请求后就可以shutdown()写端,然后收到server发来的应答,最后close掉连接。也可以不shutdown()写,等读完直接close。对于Keep-Alive的情况,就要看client的心情了,收到消息后可以断,也可以不断,server应该保证不主动断开。 20 | 21 | * 对于server端,毫无疑问应该谨慎处理以上所有情况。具体说来: 22 | > * 出现各种关于连接的错误时,可以直接close()掉 23 | > * 短连接超时的请求,可以close(),也可以不关 24 | > * 长连接对方长时间没有请求(如果没有保活机制),可以close(),也可以不关 25 | > * client发出Fin,server会收到0字节,通常不能判断client是close了还是shutdown,这时server应当把消息发完,然后才可以close(),如果对方调用的是close,会收到RST,server能感知到,就可以立即close了 26 | > * 短连接正常结束,server可以close,也可以不close,大多数的实现是不close的(对HTTP1.1而言) 27 | 28 | 29 | ##### EPOLLIN触发但是read()返回0的情况 30 | 31 | 这种情况通常有两个原因: 32 | > * 对端已经关闭了连接,这时再写该fd会出错,此时应该关闭连接 33 | > * 对端只是shutdown()了写端,告诉server我已经写完了,但是还可以接收信息。server应该在写完所有的信息后再关闭连接。更优雅的做法是透明的传递这个行为,即server顺着关闭读端,然后发完数据后关闭。 34 | -------------------------------------------------------------------------------- /WebServerCpp11/遇到的困难.md: -------------------------------------------------------------------------------- 1 | # 遇到的困难 2 | 3 | ## 1. 如何设计各个线程个任务 4 | 其实我觉的实现上的困难都不算真正的困难吧,毕竟都能写出来,无非是解决bug花的时间的长短。 5 | 我遇到的最大的问题是不太理解One loop per thread这句话吧,翻译出来不就是每个线程一个循环,我最开始写的也是一个线程一个循环啊,muduo的实现和我的有什么区别呢?还有怎么设计才能减少竞态? 6 | 7 | 带着这些问题我看了《Linux多线程服务端编程》,并看完了muduo的源码,这些问题自然而然就解决了 8 | 9 | 10 | ## 2. 异步Log几秒钟才写一次磁盘,要是coredump了,这段时间内产生的log我去哪找啊? 11 | 12 | 其实这个问题非常简单了,也没花多少时间去解决,但我觉的非常好玩。coredump了自然会保存在core文件里了,无非就是把它找出来的问题了,在这里记录一下。 13 | 14 | 当然这里不管coredump的原因是什么,我只想看丢失的log。所以模拟的话在某个地方abort()就行 15 | 16 | 多线程调试嘛,先看线程信息,info thread,找到我的异步打印线程,切换进去看bt调用栈,正常是阻塞在条件变量是wait条件中的,frame切换到threadFunc(这个函数是我的异步log里面的循环的函数名),剩下的就是print啦~不过,我的Buffer是用智能指针shared_ptr包裹的,直接->不行,gdb不识别,优化完.get()不让用,可能被inline掉了,只能直接从shared_ptr源码中找到_M_ptr成员来打印。 17 | 18 | ![gdb](https://github.com/linyacool/WebServer/blob/master/datum/gdb.png) -------------------------------------------------------------------------------- /WebServerCpp11/项目目的.md: -------------------------------------------------------------------------------- 1 | # 项目目的 2 | --- 3 | ### 最初的想法 4 | 本项目是我在三星电子(中国)研发中心实习期间利用晚上和周末的时间完成的,实习期间我负责4K分辨率双鱼眼摄像头视频拼接的算法设计与实现,我希望能把其中的图像拼接部分的成果通过Web的方式展示出来,但因为涉及保密协议,不得不放弃这一想法。 5 | 6 | ### Web服务器能够很好的贯穿所学的知识 7 | 但是,Web服务器能够很好的贯穿之前所学的知识,之前看过的《C++ Primer》、《Effevtive C++》、《STL源码剖析》、《深度探索C++对象模型》、《TCP\IP详解卷1》、APUE、UNP,还包括了《后台开发核心技术与应用实践》等书,涵盖了 8 | 9 | * TCP、HTTP协议 10 | * 多进程多线程 11 | * IO 12 | * 锁 13 | * 通信 14 | * C++语法 15 | * 编程规范 16 | * Linux环境下各种工具的使用 17 | * 版本控制Git 18 | * Makefile和CMakeLists文件的编写 19 | * 自动化构建工具Travis CI的使用 20 | 21 | 最终的版本在很多方面学习了muduo网络库,在看完陈硕的《Linux多线程服务端编程》后,对照着书把muduo的源码读了几遍,并重构了自己的服务器,最终的很多想法借鉴了muduo的思想。 22 | -------------------------------------------------------------------------------- /YouShuang/README.md: -------------------------------------------------------------------------------- 1 | # LinuxServerCodes 2 | Linux高性能服务器编程源码 3 | 4 | 作者: 游双 5 | 6 | 出版社: 机械工业出版社 7 | 8 | 出版年: 2013-5-1 9 | 10 | ISBN: 9787111425199 11 | 12 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-01 byteorder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | void byteorder() 3 | { 4 | union 5 | { 6 | short value; 7 | char union_bytes[ sizeof( short ) ]; 8 | } test; 9 | test.value = 0x0102; 10 | if ( ( test.union_bytes[ 0 ] == 1 ) && ( test.union_bytes[ 1 ] == 2 ) ) 11 | { 12 | printf( "big endian\n" ); 13 | } 14 | else if ( ( test.union_bytes[ 0 ] == 2 ) && ( test.union_bytes[ 1 ] == 1 ) ) 15 | { 16 | printf( "little endian\n" ); 17 | } 18 | else 19 | { 20 | printf( "unknown...\n" ); 21 | } 22 | } -------------------------------------------------------------------------------- /YouShuang/ch05/5-03 testlisten.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | static bool stop = false; 12 | static void handle_term( int sig ) 13 | { 14 | stop = true; 15 | } 16 | 17 | int main( int argc, char* argv[] ) 18 | { 19 | signal( SIGTERM, handle_term ); 20 | 21 | if( argc <= 3 ) 22 | { 23 | printf( "usage: %s ip_address port_number backlog\n", basename( argv[0] ) ); 24 | return 1; 25 | } 26 | const char* ip = argv[1]; 27 | int port = atoi( argv[2] ); 28 | int backlog = atoi( argv[3] ); 29 | 30 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 31 | assert( sock >= 0 ); 32 | 33 | struct sockaddr_in address; 34 | bzero( &address, sizeof( address ) ); 35 | address.sin_family = AF_INET; 36 | inet_pton( AF_INET, ip, &address.sin_addr ); 37 | address.sin_port = htons( port ); 38 | 39 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 40 | assert( ret != -1 ); 41 | 42 | ret = listen( sock, backlog ); 43 | assert( ret != -1 ); 44 | 45 | while ( ! stop ) 46 | { 47 | sleep( 1 ); 48 | } 49 | 50 | close( sock ); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-05 testaccept.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main( int argc, char* argv[] ) 12 | { 13 | if( argc <= 2 ) 14 | { 15 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 16 | return 1; 17 | } 18 | const char* ip = argv[1]; 19 | int port = atoi( argv[2] ); 20 | 21 | struct sockaddr_in address; 22 | bzero( &address, sizeof( address ) ); 23 | address.sin_family = AF_INET; 24 | inet_pton( AF_INET, ip, &address.sin_addr ); 25 | address.sin_port = htons( port ); 26 | 27 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 28 | assert( sock >= 0 ); 29 | 30 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 31 | assert( ret != -1 ); 32 | 33 | ret = listen( sock, 5 ); 34 | assert( ret != -1 ); 35 | 36 | struct sockaddr_in client; 37 | socklen_t client_addrlength = sizeof( client ); 38 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 39 | if ( connfd < 0 ) 40 | { 41 | printf( "errno is: %d\n", errno ); 42 | } 43 | else 44 | { 45 | char remote[INET_ADDRSTRLEN ]; 46 | printf( "connected with ip: %s and port: %d\n", 47 | inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) ); 48 | close( connfd ); 49 | } 50 | 51 | close( sock ); 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-06 oobsend.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main( int argc, char* argv[] ) 11 | { 12 | if( argc <= 2 ) 13 | { 14 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 15 | return 1; 16 | } 17 | const char* ip = argv[1]; 18 | int port = atoi( argv[2] ); 19 | 20 | struct sockaddr_in server_address; 21 | bzero( &server_address, sizeof( server_address ) ); 22 | server_address.sin_family = AF_INET; 23 | inet_pton( AF_INET, ip, &server_address.sin_addr ); 24 | server_address.sin_port = htons( port ); 25 | 26 | int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); 27 | assert( sockfd >= 0 ); 28 | if ( connect( sockfd, ( struct sockaddr* )&server_address, sizeof( server_address ) ) < 0 ) 29 | { 30 | printf( "connection failed\n" ); 31 | } 32 | else 33 | { 34 | printf( "send oob data out\n" ); 35 | const char* oob_data = "abc"; 36 | const char* normal_data = "123"; 37 | send( sockfd, normal_data, strlen( normal_data ), 0 ); 38 | send( sockfd, oob_data, strlen( oob_data ), MSG_OOB ); 39 | send( sockfd, normal_data, strlen( normal_data ), 0 ); 40 | } 41 | 42 | close( sockfd ); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-07 oobrecv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define BUF_SIZE 1024 12 | 13 | int main( int argc, char* argv[] ) 14 | { 15 | if( argc <= 2 ) 16 | { 17 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 18 | return 1; 19 | } 20 | const char* ip = argv[1]; 21 | int port = atoi( argv[2] ); 22 | 23 | struct sockaddr_in address; 24 | bzero( &address, sizeof( address ) ); 25 | address.sin_family = AF_INET; 26 | inet_pton( AF_INET, ip, &address.sin_addr ); 27 | address.sin_port = htons( port ); 28 | 29 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 30 | assert( sock >= 0 ); 31 | 32 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 33 | assert( ret != -1 ); 34 | 35 | ret = listen( sock, 5 ); 36 | assert( ret != -1 ); 37 | 38 | struct sockaddr_in client; 39 | socklen_t client_addrlength = sizeof( client ); 40 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 41 | if ( connfd < 0 ) 42 | { 43 | printf( "errno is: %d\n", errno ); 44 | } 45 | else 46 | { 47 | char buffer[ BUF_SIZE ]; 48 | 49 | memset( buffer, '\0', BUF_SIZE ); 50 | ret = recv( connfd, buffer, BUF_SIZE-1, 0 ); 51 | printf( "got %d bytes of normal data '%s'\n", ret, buffer ); 52 | 53 | memset( buffer, '\0', BUF_SIZE ); 54 | ret = recv( connfd, buffer, BUF_SIZE-1, MSG_OOB ); 55 | printf( "got %d bytes of oob data '%s'\n", ret, buffer ); 56 | 57 | memset( buffer, '\0', BUF_SIZE ); 58 | ret = recv( connfd, buffer, BUF_SIZE-1, 0 ); 59 | printf( "got %d bytes of normal data '%s'\n", ret, buffer ); 60 | 61 | close( connfd ); 62 | } 63 | 64 | close( sock ); 65 | return 0; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-09 reuse_address.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main( int argc, char* argv[] ) 12 | { 13 | if( argc <= 2 ) 14 | { 15 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 16 | return 1; 17 | } 18 | const char* ip = argv[1]; 19 | int port = atoi( argv[2] ); 20 | 21 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 22 | assert( sock >= 0 ); 23 | int reuse = 1; 24 | setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) ); 25 | 26 | struct sockaddr_in address; 27 | bzero( &address, sizeof( address ) ); 28 | address.sin_family = AF_INET; 29 | inet_pton( AF_INET, ip, &address.sin_addr ); 30 | address.sin_port = htons( port ); 31 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 32 | assert( ret != -1 ); 33 | 34 | ret = listen( sock, 5 ); 35 | assert( ret != -1 ); 36 | 37 | struct sockaddr_in client; 38 | socklen_t client_addrlength = sizeof( client ); 39 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 40 | if ( connfd < 0 ) 41 | { 42 | printf( "errno is: %d\n", errno ); 43 | } 44 | else 45 | { 46 | char remote[INET_ADDRSTRLEN ]; 47 | printf( "connected with ip: %s and port: %d\n", 48 | inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) ); 49 | close( connfd ); 50 | } 51 | 52 | close( sock ); 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-10 set_send_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define BUFFER_SIZE 512 10 | 11 | int main( int argc, char* argv[] ) 12 | { 13 | if( argc <= 3 ) 14 | { 15 | printf( "usage: %s ip_address port_number send_bufer_size\n", basename( argv[0] ) ); 16 | return 1; 17 | } 18 | const char* ip = argv[1]; 19 | int port = atoi( argv[2] ); 20 | 21 | struct sockaddr_in server_address; 22 | bzero( &server_address, sizeof( server_address ) ); 23 | server_address.sin_family = AF_INET; 24 | inet_pton( AF_INET, ip, &server_address.sin_addr ); 25 | server_address.sin_port = htons( port ); 26 | 27 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 28 | assert( sock >= 0 ); 29 | 30 | int sendbuf = atoi( argv[3] ); 31 | int len = sizeof( sendbuf ); 32 | setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) ); 33 | getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len ); 34 | printf( "the tcp send buffer size after setting is %d\n", sendbuf ); 35 | 36 | if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 ) 37 | { 38 | char buffer[ BUFFER_SIZE ]; 39 | memset( buffer, 'a', BUFFER_SIZE ); 40 | send( sock, buffer, BUFFER_SIZE, 0 ); 41 | } 42 | 43 | close( sock ); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-11 set_recv_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define BUFFER_SIZE 1024 12 | 13 | int main( int argc, char* argv[] ) 14 | { 15 | if( argc <= 3 ) 16 | { 17 | printf( "usage: %s ip_address port_number receive_buffer_size\n", basename( argv[0] ) ); 18 | return 1; 19 | } 20 | const char* ip = argv[1]; 21 | int port = atoi( argv[2] ); 22 | 23 | struct sockaddr_in address; 24 | bzero( &address, sizeof( address ) ); 25 | address.sin_family = AF_INET; 26 | inet_pton( AF_INET, ip, &address.sin_addr ); 27 | address.sin_port = htons( port ); 28 | 29 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 30 | assert( sock >= 0 ); 31 | int recvbuf = atoi( argv[3] ); 32 | int len = sizeof( recvbuf ); 33 | setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) ); 34 | getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len ); 35 | printf( "the receive buffer size after settting is %d\n", recvbuf ); 36 | 37 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 38 | assert( ret != -1 ); 39 | 40 | ret = listen( sock, 5 ); 41 | assert( ret != -1 ); 42 | 43 | struct sockaddr_in client; 44 | socklen_t client_addrlength = sizeof( client ); 45 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 46 | if ( connfd < 0 ) 47 | { 48 | printf( "errno is: %d\n", errno ); 49 | } 50 | else 51 | { 52 | char buffer[ BUFFER_SIZE ]; 53 | memset( buffer, '\0', BUFFER_SIZE ); 54 | while( recv( connfd, buffer, BUFFER_SIZE-1, 0 ) > 0 ){} 55 | close( connfd ); 56 | } 57 | 58 | close( sock ); 59 | return 0; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /YouShuang/ch05/5-12 access_daytime.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main( int argc, char *argv[] ) 9 | { 10 | assert( argc == 2 ); 11 | char *host = argv[1]; 12 | struct hostent* hostinfo = gethostbyname( host ); 13 | assert( hostinfo ); 14 | struct servent* servinfo = getservbyname( "daytime", "tcp" ); 15 | assert( servinfo ); 16 | printf( "daytime port is %d\n", ntohs( servinfo->s_port ) ); 17 | 18 | struct sockaddr_in address; 19 | address.sin_family = AF_INET; 20 | address.sin_port = servinfo->s_port; 21 | address.sin_addr = *( struct in_addr* )*hostinfo->h_addr_list; 22 | 23 | int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); 24 | int result = connect( sockfd, (struct sockaddr* )&address, sizeof( address ) ); 25 | assert( result != -1 ); 26 | 27 | char buffer[128]; 28 | result = read( sockfd, buffer, sizeof( buffer ) ); 29 | assert( result > 0 ); 30 | buffer[ result ] = '\0'; 31 | printf( "the day tiem is: %s", buffer ); 32 | close( sockfd ); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /YouShuang/ch06/6-01 testdup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main( int argc, char* argv[] ) 12 | { 13 | if( argc <= 2 ) 14 | { 15 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 16 | return 1; 17 | } 18 | const char* ip = argv[1]; 19 | int port = atoi( argv[2] ); 20 | 21 | struct sockaddr_in address; 22 | bzero( &address, sizeof( address ) ); 23 | address.sin_family = AF_INET; 24 | inet_pton( AF_INET, ip, &address.sin_addr ); 25 | address.sin_port = htons( port ); 26 | 27 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 28 | assert( sock >= 0 ); 29 | 30 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 31 | assert( ret != -1 ); 32 | 33 | ret = listen( sock, 5 ); 34 | assert( ret != -1 ); 35 | 36 | struct sockaddr_in client; 37 | socklen_t client_addrlength = sizeof( client ); 38 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 39 | if ( connfd < 0 ) 40 | { 41 | printf( "errno is: %d\n", errno ); 42 | } 43 | else 44 | { 45 | close( STDOUT_FILENO ); 46 | dup( connfd ); 47 | printf( "abcd\n" ); 48 | close( connfd ); 49 | } 50 | 51 | close( sock ); 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /YouShuang/ch06/6-03 testsendfile.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main( int argc, char* argv[] ) 16 | { 17 | if( argc <= 3 ) 18 | { 19 | printf( "usage: %s ip_address port_number filename\n", basename( argv[0] ) ); 20 | return 1; 21 | } 22 | const char* ip = argv[1]; 23 | int port = atoi( argv[2] ); 24 | const char* file_name = argv[3]; 25 | 26 | int filefd = open( file_name, O_RDONLY ); 27 | assert( filefd > 0 ); 28 | struct stat stat_buf; 29 | fstat( filefd, &stat_buf ); 30 | 31 | struct sockaddr_in address; 32 | bzero( &address, sizeof( address ) ); 33 | address.sin_family = AF_INET; 34 | inet_pton( AF_INET, ip, &address.sin_addr ); 35 | address.sin_port = htons( port ); 36 | 37 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 38 | assert( sock >= 0 ); 39 | 40 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 41 | assert( ret != -1 ); 42 | 43 | ret = listen( sock, 5 ); 44 | assert( ret != -1 ); 45 | 46 | struct sockaddr_in client; 47 | socklen_t client_addrlength = sizeof( client ); 48 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 49 | if ( connfd < 0 ) 50 | { 51 | printf( "errno is: %d\n", errno ); 52 | } 53 | else 54 | { 55 | sendfile( connfd, filefd, NULL, stat_buf.st_size ); 56 | close( connfd ); 57 | } 58 | 59 | close( sock ); 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /YouShuang/ch06/6-04 testsplice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main( int argc, char* argv[] ) 13 | { 14 | if( argc <= 2 ) 15 | { 16 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 17 | return 1; 18 | } 19 | const char* ip = argv[1]; 20 | int port = atoi( argv[2] ); 21 | 22 | struct sockaddr_in address; 23 | bzero( &address, sizeof( address ) ); 24 | address.sin_family = AF_INET; 25 | inet_pton( AF_INET, ip, &address.sin_addr ); 26 | address.sin_port = htons( port ); 27 | 28 | int sock = socket( PF_INET, SOCK_STREAM, 0 ); 29 | assert( sock >= 0 ); 30 | 31 | int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); 32 | assert( ret != -1 ); 33 | 34 | ret = listen( sock, 5 ); 35 | assert( ret != -1 ); 36 | 37 | struct sockaddr_in client; 38 | socklen_t client_addrlength = sizeof( client ); 39 | int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); 40 | if ( connfd < 0 ) 41 | { 42 | printf( "errno is: %d\n", errno ); 43 | } 44 | else 45 | { 46 | int pipefd[2]; 47 | assert( ret != -1 ); 48 | ret = pipe( pipefd ); 49 | ret = splice( connfd, NULL, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE ); 50 | assert( ret != -1 ); 51 | ret = splice( pipefd[0], NULL, connfd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE ); 52 | assert( ret != -1 ); 53 | close( connfd ); 54 | } 55 | 56 | close( sock ); 57 | return 0; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /YouShuang/ch06/6-05 testtee.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main( int argc, char* argv[] ) 9 | { 10 | if ( argc != 2 ) 11 | { 12 | printf( "usage: %s \n", argv[0] ); 13 | return 1; 14 | } 15 | int filefd = open( argv[1], O_CREAT | O_WRONLY | O_TRUNC, 0666 ); 16 | assert( filefd > 0 ); 17 | 18 | int pipefd_stdout[2]; 19 | int ret = pipe( pipefd_stdout ); 20 | assert( ret != -1 ); 21 | 22 | int pipefd_file[2]; 23 | ret = pipe( pipefd_file ); 24 | assert( ret != -1 ); 25 | 26 | //close( STDIN_FILENO ); 27 | // dup2( pipefd_stdout[1], STDIN_FILENO ); 28 | //write( pipefd_stdout[1], "abc\n", 4 ); 29 | ret = splice( STDIN_FILENO, NULL, pipefd_stdout[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE ); 30 | assert( ret != -1 ); 31 | ret = tee( pipefd_stdout[0], pipefd_file[1], 32768, SPLICE_F_NONBLOCK ); 32 | assert( ret != -1 ); 33 | ret = splice( pipefd_file[0], NULL, filefd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE ); 34 | assert( ret != -1 ); 35 | ret = splice( pipefd_stdout[0], NULL, STDOUT_FILENO, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE ); 36 | assert( ret != -1 ); 37 | 38 | close( filefd ); 39 | close( pipefd_stdout[0] ); 40 | close( pipefd_stdout[1] ); 41 | close( pipefd_file[0] ); 42 | close( pipefd_file[1] ); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /YouShuang/ch07/7-01 testeuid.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | uid_t uid = getuid(); 7 | uid_t euid = geteuid(); 8 | printf( "userid is %d, effective userid is: %d\n", uid, euid ); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /YouShuang/ch07/7-02 switchuser.cpp: -------------------------------------------------------------------------------- 1 | static bool switch_to_user( uid_t user_id, gid_t gp_id ) 2 | { 3 | if ( ( user_id == 0 ) && ( gp_id == 0 ) ) 4 | { 5 | return false; 6 | } 7 | 8 | gid_t gid = getgid(); 9 | uid_t uid = getuid(); 10 | if ( ( ( gid != 0 ) || ( uid != 0 ) ) && ( ( gid != gp_id ) || ( uid != user_id ) ) ) 11 | { 12 | return false; 13 | } 14 | 15 | if ( uid != 0 ) 16 | { 17 | return true; 18 | } 19 | 20 | if ( ( setgid( gp_id ) < 0 ) || ( setuid( user_id ) < 0 ) ) 21 | { 22 | return false; 23 | } 24 | 25 | return true; 26 | } -------------------------------------------------------------------------------- /YouShuang/ch07/7-03 daemonize.cpp: -------------------------------------------------------------------------------- 1 | bool daemonize() 2 | { 3 | pid_t pid = fork(); 4 | if ( pid < 0 ) 5 | { 6 | return false; 7 | } 8 | else if ( pid > 0 ) 9 | { 10 | exit( 0 ); 11 | } 12 | 13 | umask( 0 ); 14 | 15 | pid_t sid = setsid(); 16 | if ( sid < 0 ) 17 | { 18 | return false; 19 | } 20 | 21 | if ( ( chdir( "/" ) ) < 0 ) 22 | { 23 | /* Log the failure */ 24 | return false; 25 | } 26 | 27 | close( STDIN_FILENO ); 28 | close( STDOUT_FILENO ); 29 | close( STDERR_FILENO ); 30 | 31 | open( "/dev/null", O_RDONLY ); 32 | open( "/dev/null", O_RDWR ); 33 | open( "/dev/null", O_RDWR ); 34 | return true; 35 | } -------------------------------------------------------------------------------- /YouShuang/ch11/11-01 connect_timeout.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int timeout_connect( const char* ip, int port, int time ) 14 | { 15 | int ret = 0; 16 | struct sockaddr_in address; 17 | bzero( &address, sizeof( address ) ); 18 | address.sin_family = AF_INET; 19 | inet_pton( AF_INET, ip, &address.sin_addr ); 20 | address.sin_port = htons( port ); 21 | 22 | int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); 23 | assert( sockfd >= 0 ); 24 | 25 | struct timeval timeout; 26 | timeout.tv_sec = time; 27 | timeout.tv_usec = 0; 28 | socklen_t len = sizeof( timeout ); 29 | ret = setsockopt( sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, len ); 30 | assert( ret != -1 ); 31 | 32 | ret = connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) ); 33 | if ( ret == -1 ) 34 | { 35 | if( errno == EINPROGRESS ) 36 | { 37 | printf( "connecting timeout\n" ); 38 | return -1; 39 | } 40 | printf( "error occur when connecting to server\n" ); 41 | return -1; 42 | } 43 | 44 | return sockfd; 45 | } 46 | 47 | int main( int argc, char* argv[] ) 48 | { 49 | if( argc <= 2 ) 50 | { 51 | printf( "usage: %s ip_address port_number\n", basename( argv[0] ) ); 52 | return 1; 53 | } 54 | const char* ip = argv[1]; 55 | int port = atoi( argv[2] ); 56 | 57 | int sockfd = timeout_connect( ip, port, 10 ); 58 | if ( sockfd < 0 ) 59 | { 60 | return 1; 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /YouShuang/ch11/11-04 io_timer.cpp: -------------------------------------------------------------------------------- 1 | #define TIMEOUT 5000 2 | 3 | int timeout = TIMEOUT; 4 | time_t start = time( NULL ); 5 | time_t end = time( NULL ); 6 | while( 1 ) 7 | { 8 | printf( "the timeout is now %d mill-seconds\n", timeout ); 9 | start = time( NULL ); 10 | int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, timeout ); 11 | if( ( number < 0 ) && ( errno != EINTR ) ) 12 | { 13 | printf( "epoll failure\n" ); 14 | break; 15 | } 16 | if( number == 0 ) 17 | { 18 | // timeout 19 | timeout = TIMEOUT; 20 | continue; 21 | } 22 | 23 | end = time( NULL ); 24 | timeout -= ( end - start ) * 1000; 25 | if( timeout <= 0 ) 26 | { 27 | // timeout 28 | timeout = TIMEOUT; 29 | } 30 | 31 | // handle connections 32 | } 33 | -------------------------------------------------------------------------------- /YouShuang/ch12/12-01 libevent_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void signal_cb( int fd, short event, void* argc ) 5 | { 6 | struct event_base* base = ( event_base* )argc; 7 | struct timeval delay = { 2, 0 }; 8 | printf( "Caught an interrupt signal; exiting cleanly in two seconds...\n" ); 9 | event_base_loopexit( base, &delay ); 10 | } 11 | 12 | void timeout_cb( int fd, short event, void* argc ) 13 | { 14 | printf( "timeout\n" ); 15 | } 16 | 17 | int main() 18 | { 19 | struct event_base* base = event_init(); 20 | 21 | struct event* signal_event = evsignal_new( base, SIGINT, signal_cb, base ); 22 | event_add( signal_event, NULL ); 23 | 24 | timeval tv = { 1, 0 }; 25 | struct event* timeout_event = evtimer_new( base, timeout_cb, NULL ); 26 | event_add( timeout_event, &tv ); 27 | 28 | event_base_dispatch( base ); 29 | 30 | event_free( timeout_event ); 31 | event_free( signal_event ); 32 | event_base_free( base ); 33 | } 34 | -------------------------------------------------------------------------------- /YouShuang/ch13/13-03 sem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | union semun 8 | { 9 | int val; 10 | struct semid_ds* buf; 11 | unsigned short int* array; 12 | struct seminfo* __buf; 13 | }; 14 | 15 | void pv( int sem_id, int op ) 16 | { 17 | struct sembuf sem_b; 18 | sem_b.sem_num = 0; 19 | sem_b.sem_op = op; 20 | sem_b.sem_flg = SEM_UNDO; 21 | semop( sem_id, &sem_b, 1 ); 22 | } 23 | 24 | int main( int argc, char* argv[] ) 25 | { 26 | int sem_id = semget( IPC_PRIVATE, 1, 0666 ); 27 | 28 | union semun sem_un; 29 | sem_un.val = 1; 30 | semctl( sem_id, 0, SETVAL, sem_un ); 31 | 32 | pid_t id = fork(); 33 | if( id < 0 ) 34 | { 35 | return 1; 36 | } 37 | else if( id == 0 ) 38 | { 39 | printf( "child try to get binary sem\n" ); 40 | pv( sem_id, -1 ); 41 | printf( "child get the sem and would release it after 5 seconds\n" ); 42 | sleep( 5 ); 43 | pv( sem_id, 1 ); 44 | exit( 0 ); 45 | } 46 | else 47 | { 48 | printf( "parent try to get binary sem\n" ); 49 | pv( sem_id, -1 ); 50 | printf( "parent get the sem and would release it after 5 seconds\n" ); 51 | sleep( 5 ); 52 | pv( sem_id, 1 ); 53 | } 54 | 55 | waitpid( id, NULL, 0 ); 56 | semctl( sem_id, 0, IPC_RMID, sem_un ); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /YouShuang/ch13/13-05 passfd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static const int CONTROL_LEN = CMSG_LEN( sizeof(int) ); 10 | 11 | void send_fd( int fd, int fd_to_send ) 12 | { 13 | struct iovec iov[1]; 14 | struct msghdr msg; 15 | char buf[0]; 16 | 17 | iov[0].iov_base = buf; 18 | iov[0].iov_len = 1; 19 | msg.msg_name = NULL; 20 | msg.msg_namelen = 0; 21 | msg.msg_iov = iov; 22 | msg.msg_iovlen = 1; 23 | 24 | cmsghdr cm; 25 | cm.cmsg_len = CONTROL_LEN; 26 | cm.cmsg_level = SOL_SOCKET; 27 | cm.cmsg_type = SCM_RIGHTS; 28 | *(int *)CMSG_DATA( &cm ) = fd_to_send; 29 | msg.msg_control = &cm; 30 | msg.msg_controllen = CONTROL_LEN; 31 | 32 | sendmsg( fd, &msg, 0 ); 33 | } 34 | 35 | int recv_fd( int fd ) 36 | { 37 | struct iovec iov[1]; 38 | struct msghdr msg; 39 | char buf[0]; 40 | 41 | iov[0].iov_base = buf; 42 | iov[0].iov_len = 1; 43 | msg.msg_name = NULL; 44 | msg.msg_namelen = 0; 45 | msg.msg_iov = iov; 46 | msg.msg_iovlen = 1; 47 | 48 | cmsghdr cm; 49 | msg.msg_control = &cm; 50 | msg.msg_controllen = CONTROL_LEN; 51 | 52 | recvmsg( fd, &msg, 0 ); 53 | 54 | int fd_to_read = *(int *)CMSG_DATA( &cm ); 55 | return fd_to_read; 56 | } 57 | 58 | int main() 59 | { 60 | int pipefd[2]; 61 | int fd_to_pass = 0; 62 | 63 | int ret = socketpair( PF_UNIX, SOCK_DGRAM, 0, pipefd ); 64 | assert( ret != -1 ); 65 | 66 | pid_t pid = fork(); 67 | assert( pid >= 0 ); 68 | 69 | if ( pid == 0 ) 70 | { 71 | close( pipefd[0] ); 72 | fd_to_pass = open( "test.txt", O_RDWR, 0666 ); 73 | send_fd( pipefd[1], ( fd_to_pass > 0 ) ? fd_to_pass : 0 ); 74 | close( fd_to_pass ); 75 | exit( 0 ); 76 | } 77 | 78 | close( pipefd[1] ); 79 | fd_to_pass = recv_fd( pipefd[0] ); 80 | char buf[1024]; 81 | memset( buf, '\0', 1024 ); 82 | read( fd_to_pass, buf, 1024 ); 83 | printf( "I got fd %d and data %s\n", fd_to_pass, buf ); 84 | close( fd_to_pass ); 85 | } 86 | -------------------------------------------------------------------------------- /YouShuang/ch14/14-01 mutual_lock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int a = 0; 6 | int b = 0; 7 | pthread_mutex_t mutex_a; 8 | pthread_mutex_t mutex_b; 9 | 10 | void* another( void* arg ) 11 | { 12 | pthread_mutex_lock( &mutex_b ); 13 | printf( "in child thread, got mutex b, waiting for mutex a\n" ); 14 | sleep( 5 ); 15 | ++b; 16 | pthread_mutex_lock( &mutex_a ); 17 | b += a++; 18 | pthread_mutex_unlock( &mutex_a ); 19 | pthread_mutex_unlock( &mutex_b ); 20 | pthread_exit( NULL ); 21 | } 22 | 23 | int main() 24 | { 25 | pthread_t id; 26 | 27 | pthread_mutex_init( &mutex_a, NULL ); 28 | pthread_mutex_init( &mutex_b, NULL ); 29 | pthread_create( &id, NULL, another, NULL ); 30 | 31 | pthread_mutex_lock( &mutex_a ); 32 | printf( "in parent thread, got mutex a, waiting for mutex b\n" ); 33 | sleep( 5 ); 34 | ++a; 35 | pthread_mutex_lock( &mutex_b ); 36 | a += b++; 37 | pthread_mutex_unlock( &mutex_b ); 38 | pthread_mutex_unlock( &mutex_a ); 39 | 40 | pthread_join( id, NULL ); 41 | pthread_mutex_destroy( &mutex_a ); 42 | pthread_mutex_destroy( &mutex_b ); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /YouShuang/ch14/14-02 locker.h: -------------------------------------------------------------------------------- 1 | #ifndef LOCKER_H 2 | #define LOCKER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class sem 9 | { 10 | public: 11 | sem() 12 | { 13 | if( sem_init( &m_sem, 0, 0 ) != 0 ) 14 | { 15 | throw std::exception(); 16 | } 17 | } 18 | ~sem() 19 | { 20 | sem_destroy( &m_sem ); 21 | } 22 | bool wait() 23 | { 24 | return sem_wait( &m_sem ) == 0; 25 | } 26 | bool post() 27 | { 28 | return sem_post( &m_sem ) == 0; 29 | } 30 | 31 | private: 32 | sem_t m_sem; 33 | }; 34 | 35 | class locker 36 | { 37 | public: 38 | locker() 39 | { 40 | if( pthread_mutex_init( &m_mutex, NULL ) != 0 ) 41 | { 42 | throw std::exception(); 43 | } 44 | } 45 | ~locker() 46 | { 47 | pthread_mutex_destroy( &m_mutex ); 48 | } 49 | bool lock() 50 | { 51 | return pthread_mutex_lock( &m_mutex ) == 0; 52 | } 53 | bool unlock() 54 | { 55 | return pthread_mutex_unlock( &m_mutex ) == 0; 56 | } 57 | 58 | private: 59 | pthread_mutex_t m_mutex; 60 | }; 61 | 62 | class cond 63 | { 64 | public: 65 | cond() 66 | { 67 | if( pthread_mutex_init( &m_mutex, NULL ) != 0 ) 68 | { 69 | throw std::exception(); 70 | } 71 | if ( pthread_cond_init( &m_cond, NULL ) != 0 ) 72 | { 73 | pthread_mutex_destroy( &m_mutex ); 74 | throw std::exception(); 75 | } 76 | } 77 | ~cond() 78 | { 79 | pthread_mutex_destroy( &m_mutex ); 80 | pthread_cond_destroy( &m_cond ); 81 | } 82 | bool wait() 83 | { 84 | int ret = 0; 85 | pthread_mutex_lock( &m_mutex ); 86 | ret = pthread_cond_wait( &m_cond, &m_mutex ); 87 | pthread_mutex_unlock( &m_mutex ); 88 | return ret == 0; 89 | } 90 | bool signal() 91 | { 92 | return pthread_cond_signal( &m_cond ) == 0; 93 | } 94 | 95 | private: 96 | pthread_mutex_t m_mutex; 97 | pthread_cond_t m_cond; 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /YouShuang/ch14/14-03 thread_atfork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | pthread_mutex_t mutex; 8 | 9 | void* another( void* arg ) 10 | { 11 | printf( "in child thread, lock the mutex\n" ); 12 | pthread_mutex_lock( &mutex ); 13 | sleep( 5 ); 14 | pthread_mutex_unlock( &mutex ); 15 | } 16 | 17 | void prepare() 18 | { 19 | pthread_mutex_lock( &mutex ); 20 | } 21 | 22 | void infork() 23 | { 24 | pthread_mutex_unlock( &mutex ); 25 | } 26 | 27 | int main() 28 | { 29 | pthread_mutex_init( &mutex, NULL ); 30 | pthread_t id; 31 | pthread_create( &id, NULL, another, NULL ); 32 | //pthread_atfork( prepare, infork, infork ); 33 | sleep( 1 ); 34 | int pid = fork(); 35 | if( pid < 0 ) 36 | { 37 | pthread_join( id, NULL ); 38 | pthread_mutex_destroy( &mutex ); 39 | return 1; 40 | } 41 | else if( pid == 0 ) 42 | { 43 | printf( "I anm in the child, want to get the lock\n" ); 44 | pthread_mutex_lock( &mutex ); 45 | printf( "I can not run to here, oop...\n" ); 46 | pthread_mutex_unlock( &mutex ); 47 | exit( 0 ); 48 | } 49 | else 50 | { 51 | pthread_mutex_unlock( &mutex ); 52 | wait( NULL ); 53 | } 54 | pthread_join( id, NULL ); 55 | pthread_mutex_destroy( &mutex ); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /YouShuang/ch14/14-05 sigmask.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* Simple error handling functions */ 9 | 10 | #define handle_error_en(en, msg) \ 11 | do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) 12 | 13 | static void * 14 | sig_thread(void *arg) 15 | { 16 | printf( "yyyyy, thread id is: %ld\n", pthread_self() ); 17 | sigset_t aset; 18 | int s, sig; 19 | sigemptyset(&aset); 20 | sigaddset(&aset, SIGQUIT); 21 | sigaddset(&aset, SIGUSR1); 22 | //s = pthread_sigmask(SIG_BLOCK, &aset, NULL); 23 | sigset_t *set = (sigset_t *) arg; 24 | 25 | for (;;) { 26 | s = sigwait(set, &sig); 27 | if (s != 0) 28 | handle_error_en(s, "sigwait"); 29 | printf("Signal handling thread got signal %d\n", sig); 30 | } 31 | } 32 | 33 | static void handler( int arg ) 34 | { 35 | printf( "xxxxx, thread id is: %ld\n", pthread_self() ); 36 | } 37 | 38 | int 39 | main(int argc, char *argv[]) 40 | { 41 | pthread_t thread; 42 | sigset_t set; 43 | int s; 44 | 45 | /* Block SIGINT; other threads created by main() will inherit 46 | * a copy of the signal mask. */ 47 | 48 | signal( SIGQUIT, handler ); 49 | // if (s != 0) 50 | // handle_error_en(s, "pthread_sigmask"); 51 | 52 | s = pthread_create(&thread, NULL, &sig_thread, (void *) &set); 53 | sigemptyset(&set); 54 | sigaddset(&set, SIGQUIT); 55 | sigaddset(&set, SIGUSR1); 56 | //s = pthread_sigmask(SIG_BLOCK, &set, NULL); 57 | if (s != 0) 58 | handle_error_en(s, "pthread_create"); 59 | printf( "sub thread with id: %ld\n", thread ); 60 | /* Main thread carries on to create other threads and/or do 61 | * other work */ 62 | 63 | pause(); /* Dummy pause so we can test program */ 64 | } 65 | 66 | -------------------------------------------------------------------------------- /YouShuang/rename.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | # print(os.listdir()) 5 | for folder in os.listdir()[:]: 6 | if folder.startswith("ch"): 7 | print(folder) 8 | for fn in os.listdir(folder): 9 | print("\t"+fn) 10 | res = re.findall("(\d+)(-)(\d+)\s*(.*)", fn) 11 | if res: 12 | res = res[0] 13 | # print("{}{}{:0>2} {}".format(res[0],res[1],res[2],res[3])) 14 | new_fn = "{}{}{:0>2} {}".format(res[0],res[1],res[2],res[3]) 15 | print("\t -> "+new_fn) 16 | os.rename(folder+"/"+fn, folder+"/"+new_fn) -------------------------------------------------------------------------------- /YouShuang/springsnail/Makefile: -------------------------------------------------------------------------------- 1 | all: log.o fdwrapper.o conn.o mgr.o springsnail 2 | 3 | log.o: log.cpp log.h 4 | g++ -c log.cpp -o log.o 5 | fdwrapper.o: fdwrapper.cpp fdwrapper.h 6 | g++ -c fdwrapper.cpp -o fdwrapper.o 7 | conn.o: conn.cpp conn.h 8 | g++ -c conn.cpp -o conn.o 9 | mgr.o: mgr.cpp mgr.h 10 | g++ -c mgr.cpp -o mgr.o 11 | springsnail: processpool.h main.cpp log.o fdwrapper.o conn.o mgr.o 12 | g++ processpool.h log.o fdwrapper.o conn.o mgr.o main.cpp -o springsnail 13 | 14 | clean: 15 | rm *.o springsnail 16 | -------------------------------------------------------------------------------- /YouShuang/springsnail/config.xml: -------------------------------------------------------------------------------- 1 | Listen 10.194.70.225:12345 2 | 3 | 4 | 10.194.70.225 5 | 13579 6 | 5 7 | 8 | 9 | 10.194.70.79 10 | 13579 11 | 5 12 | 13 | -------------------------------------------------------------------------------- /YouShuang/springsnail/conn.h: -------------------------------------------------------------------------------- 1 | #ifndef CONN_H 2 | #define CONN_H 3 | 4 | #include 5 | #include "fdwrapper.h" 6 | 7 | class conn 8 | { 9 | public: 10 | conn(); 11 | ~conn(); 12 | void init_clt( int sockfd, const sockaddr_in& client_addr ); 13 | void init_srv( int sockfd, const sockaddr_in& server_addr ); 14 | void reset(); 15 | RET_CODE read_clt(); 16 | RET_CODE write_clt(); 17 | RET_CODE read_srv(); 18 | RET_CODE write_srv(); 19 | 20 | public: 21 | static const int BUF_SIZE = 2048; 22 | 23 | char* m_clt_buf; 24 | int m_clt_read_idx; 25 | int m_clt_write_idx; 26 | sockaddr_in m_clt_address; 27 | int m_cltfd; 28 | 29 | char* m_srv_buf; 30 | int m_srv_read_idx; 31 | int m_srv_write_idx; 32 | sockaddr_in m_srv_address; 33 | int m_srvfd; 34 | 35 | bool m_srv_closed; 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /YouShuang/springsnail/fdwrapper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef FDWRAPPER_H 2 | #define FDWRAPPER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | int setnonblocking( int fd ) 9 | { 10 | int old_option = fcntl( fd, F_GETFL ); 11 | int new_option = old_option | O_NONBLOCK; 12 | fcntl( fd, F_SETFL, new_option ); 13 | return old_option; 14 | } 15 | 16 | void add_read_fd( int epollfd, int fd ) 17 | { 18 | epoll_event event; 19 | event.data.fd = fd; 20 | event.events = EPOLLIN | EPOLLET; 21 | epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); 22 | setnonblocking( fd ); 23 | } 24 | 25 | void add_write_fd( int epollfd, int fd ) 26 | { 27 | epoll_event event; 28 | event.data.fd = fd; 29 | event.events = EPOLLOUT | EPOLLET; 30 | epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); 31 | setnonblocking( fd ); 32 | } 33 | 34 | void closefd( int epollfd, int fd ) 35 | { 36 | epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 ); 37 | close( fd ); 38 | } 39 | 40 | void removefd( int epollfd, int fd ) 41 | { 42 | epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 ); 43 | } 44 | 45 | void modfd( int epollfd, int fd, int ev ) 46 | { 47 | epoll_event event; 48 | event.data.fd = fd; 49 | event.events = ev | EPOLLET; 50 | epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event ); 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /YouShuang/springsnail/fdwrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef FDWRAPPER_H 2 | #define FDWRAPPER_H 3 | 4 | enum RET_CODE { OK = 0, NOTHING = 1, IOERR = -1, CLOSED = -2, BUFFER_FULL = -3, BUFFER_EMPTY = -4, TRY_AGAIN }; 5 | enum OP_TYPE { READ = 0, WRITE, ERROR }; 6 | int setnonblocking( int fd ); 7 | void add_read_fd( int epollfd, int fd ); 8 | void add_write_fd( int epollfd, int fd ); 9 | void removefd( int epollfd, int fd ); 10 | void closefd( int epollfd, int fd ); 11 | void modfd( int epollfd, int fd, int ev ); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /YouShuang/springsnail/log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "log.h" 5 | 6 | static int level = LOG_INFO; 7 | static int LOG_BUFFER_SIZE = 2048; 8 | static const char* loglevels[] = 9 | { 10 | "emerge!", "alert!", "critical!", "error!", "warn!", "notice:", "info:", "debug:" 11 | }; 12 | 13 | void set_loglevel( int log_level ) 14 | { 15 | level = log_level; 16 | } 17 | 18 | void log( int log_level, const char* file_name, int line_num, const char* format, ... ) 19 | { 20 | if ( log_level > level ) 21 | { 22 | return; 23 | } 24 | 25 | time_t tmp = time( NULL ); 26 | struct tm* cur_time = localtime( &tmp ); 27 | if ( ! cur_time ) 28 | { 29 | return; 30 | } 31 | 32 | char arg_buffer[ LOG_BUFFER_SIZE ]; 33 | memset( arg_buffer, '\0', LOG_BUFFER_SIZE ); 34 | strftime( arg_buffer, LOG_BUFFER_SIZE - 1, "[ %x %X ] ", cur_time ); 35 | printf( "%s", arg_buffer ); 36 | printf( "%s:%04d ", file_name, line_num ); 37 | printf( "%s ", loglevels[ log_level - LOG_EMERG ] ); 38 | 39 | va_list arg_list; 40 | va_start( arg_list, format ); 41 | memset( arg_buffer, '\0', LOG_BUFFER_SIZE ); 42 | vsnprintf( arg_buffer, LOG_BUFFER_SIZE - 1, format, arg_list ); 43 | printf( "%s\n", arg_buffer ); 44 | fflush( stdout ); 45 | va_end( arg_list ); 46 | } 47 | -------------------------------------------------------------------------------- /YouShuang/springsnail/log.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_H 2 | #define LOG_H 3 | 4 | #include 5 | #include 6 | 7 | void set_loglevel( int log_level = LOG_DEBUG ); 8 | void log( int log_level, const char* file_name, int line_num, const char* format, ... ); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /YouShuang/springsnail/mgr.h: -------------------------------------------------------------------------------- 1 | #ifndef SRVMGR_H 2 | #define SRVMGR_H 3 | 4 | #include 5 | #include 6 | #include "fdwrapper.h" 7 | #include "conn.h" 8 | 9 | using std::map; 10 | 11 | class host 12 | { 13 | public: 14 | char m_hostname[1024]; 15 | int m_port; 16 | int m_conncnt; 17 | }; 18 | 19 | class mgr 20 | { 21 | public: 22 | mgr( int epollfd, const host& srv ); 23 | ~mgr(); 24 | int conn2srv( const sockaddr_in& address ); 25 | conn* pick_conn( int sockfd ); 26 | void free_conn( conn* connection ); 27 | int get_used_conn_cnt(); 28 | void recycle_conns(); 29 | RET_CODE process( int fd, OP_TYPE type ); 30 | 31 | private: 32 | static int m_epollfd; 33 | map< int, conn* > m_conns; 34 | map< int, conn* > m_used; 35 | map< int, conn* > m_freed; 36 | host m_logic_srv; 37 | }; 38 | 39 | #endif 40 | --------------------------------------------------------------------------------