├── Client
├── Codes
│ ├── README.md
│ ├── client.pro
│ └── main.cpp
└── Debug
│ ├── client
│ ├── main.o
│ └── Makefile
├── runClient.png
├── runServer.png
├── Server
├── Debug
│ ├── main.o
│ ├── server
│ ├── cgi-bin
│ │ └── adder
│ ├── html
│ │ └── index.html
│ └── Makefile
└── Codes
│ ├── server.pro
│ ├── README.md
│ ├── main.cpp
│ ├── web_function.h
│ ├── web_thread.h
│ └── http_conn.h
└── README.md
/Client/Codes/README.md:
--------------------------------------------------------------------------------
1 | 一个针对服务器的压力测试程序,可自定义请求客户的数目
2 |
--------------------------------------------------------------------------------
/runClient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/runClient.png
--------------------------------------------------------------------------------
/runServer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/runServer.png
--------------------------------------------------------------------------------
/Client/Debug/client:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/Client/Debug/client
--------------------------------------------------------------------------------
/Client/Debug/main.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/Client/Debug/main.o
--------------------------------------------------------------------------------
/Server/Debug/main.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/Server/Debug/main.o
--------------------------------------------------------------------------------
/Server/Debug/server:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/Server/Debug/server
--------------------------------------------------------------------------------
/Server/Debug/cgi-bin/adder:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Buerzhu/TinyWeb/HEAD/Server/Debug/cgi-bin/adder
--------------------------------------------------------------------------------
/Server/Debug/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | test
4 |
5 |
6 | test
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Client/Codes/client.pro:
--------------------------------------------------------------------------------
1 | QT += core
2 | QT -= gui
3 |
4 | TARGET = client
5 | CONFIG += console
6 | QMAKE_CXXFLAGS += -std=c++11
7 | CONFIG -= app_bundle
8 |
9 | TEMPLATE = app
10 |
11 | SOURCES += main.cpp
12 |
13 |
--------------------------------------------------------------------------------
/Server/Codes/server.pro:
--------------------------------------------------------------------------------
1 | QT += core
2 | QT -= gui
3 |
4 | TARGET = server
5 | CONFIG += console
6 | CONFIG -= app_bundle
7 | QMAKE_CXXFLAGS += -std=c++0x
8 |
9 | TEMPLATE = app
10 |
11 | SOURCES += main.cpp
12 |
13 | HEADERS += \
14 | http_conn.h \
15 | web_function.h \
16 | web_thread.h
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | * **前言**
2 |
3 | 本项目是基于C++线程池的轻量级Web并发服务器,事件处理模式采用Reactor模式,主线程只负责监听文件描述符是否有事件发生,读写数据、接收新的连接、以及处理客户请求均在工作线程中实现;使用半同步/半异步模式,每个线程(主线程和工作线程)都通过一个epoll维护自己的事件循环,它们各自独立地监听不同事件。使用C++ 11的atomic原子变量来同步线程访问从而避免同步错误;使用STL的优先队列作为定时器容器来回收非活动长连接。本项目的具体设计思路可以参照本人的知乎文章[C++网络编程入门:轻量级Web并发服务器开发](https://zhuanlan.zhihu.com/p/109905285),纯属抛砖引玉,欢迎大佬们批评指正。
4 |
5 | * **运行环境**
6 |
7 | (1).系统:Ubuntu16.04;
8 |
9 | (2).语言:C++ 11及以上版本;
10 |
11 | * **支持功能**
12 |
13 | (1).支持Get请求;
14 | (2).支持长连接/短连接;
15 | (3).支持ipv4/ipv6;(4).支持tcp;(5).支持请求静态内容(6).支持并发请求
16 |
17 | * **开始运行**
18 |
19 | (1).下载程序;
20 |
21 | `git clone git@github.com:Buerzhu/TinyWeb.git`
22 |
23 | (2).打开新终端,指定ip地址和端口运行服务器程序:
24 |
25 | `cd ~/TinyWeb/Server/Debug`
26 |
27 | `./server 127.0.0.1 12345`
28 |
29 | (3).打开新终端,指定ip地址、端口、客户连接数运行压力测试程序:
30 |
31 | `cd ~/TinyWeb/Client/Debug`
32 |
33 | `./client 127.0.0.1 12345 1000`
34 |
--------------------------------------------------------------------------------
/Server/Codes/README.md:
--------------------------------------------------------------------------------
1 | * **web_thread.h**
2 |
3 | (1). 定义了webthread类;
4 |
5 | (2). 该类是主线程与子线程通信的媒介,本程序对于每个子线程建立对应的wedthread全局对象,主线程通过该对象来与子线程通信,子线程通过该对象接收来自主线程的消息,并运行该对象的work()函数来处理主线程消息和用户的http请求。
6 |
7 | * **http_conn.h**
8 |
9 | (1).定义了http_conn类和util_timer类;
10 |
11 | (2).http_conn类是用于处理http请求和作出http应答的一个类,本程序对于每个新连接的用户都分配一个http_conn对象用于处理http请求;
12 |
13 | (3).util_timer类是定时器类,本程序对于每个新连接的用户都分配一个定时器对象,并设置该定时器的超时时间,如果长连接用户在超时时间内都处于非活动状态则关闭用户连接,如果用户在超时时间到达之前重新活动则延长超时时间。
14 |
15 |
16 | * **web_function.h**
17 |
18 | (1).该文件用于定义全局变量和常量,包括线程数、当前总用户数、读写缓冲区大小等,如果要支持更多的并发用户请求,应该修改该文件中定义的这些常量;
19 |
20 | (2).该文件还提供了一些通用的基本功能函数,例如显示当前时区时间的函数,显示用户ip地址的函数等;
21 |
22 |
23 | * **main.cpp**
24 |
25 | (1). 程序运行入口
26 |
27 | (2). 主线程只负责监听文件描述符是否有事件发生而不处理面向用户的业务逻辑(Reactor模式);
28 |
29 | * **server.pro**
30 |
31 | (1). 该文件是qtcreator关于qmake的工程文件,qt通过该文件来生成Makefile文件。
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Client/Codes/main.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 | static const char* request = "GET http://localhost/html/index.html HTTP/1.1\r\nConnection: keep-alive\r\n\r\nxxxxxxxxxxxx";
14 |
15 | int setnonblocking( int fd )
16 | {
17 | int old_option = fcntl( fd, F_GETFL );
18 | int new_option = old_option | O_NONBLOCK;
19 | fcntl( fd, F_SETFL, new_option );
20 | return old_option;
21 | }
22 |
23 | void addfd( int epoll_fd, int fd )
24 | {
25 | epoll_event event;
26 | event.data.fd = fd;
27 | event.events = EPOLLOUT | EPOLLET | EPOLLERR;
28 | epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &event );
29 | setnonblocking( fd );
30 | }
31 |
32 | bool write_nbytes( int sockfd, const char* buffer, int len )
33 | {
34 | int bytes_write = 0;
35 | printf( "write out %d bytes to socket %d\n", len, sockfd );
36 | while( 1 )
37 | {
38 | bytes_write = send( sockfd, buffer, len, 0 );
39 | if ( bytes_write == -1 )
40 | {
41 | return false;
42 | }
43 | else if ( bytes_write == 0 )
44 | {
45 | return false;
46 | }
47 |
48 | len -= bytes_write;
49 | buffer = buffer + bytes_write;
50 | if ( len <= 0 )
51 | {
52 | return true;
53 | }
54 | }
55 | }
56 |
57 | bool read_once( int sockfd, char* buffer, int len )
58 | {
59 | int bytes_read = 0;
60 | memset( buffer, '\0', len );
61 | bytes_read = recv( sockfd, buffer, len, 0 );
62 | if ( bytes_read == -1 )
63 | {
64 | return false;
65 | }
66 | else if ( bytes_read == 0 )
67 | {
68 | return false;
69 | }
70 | printf( "read in %d bytes from socket %d with content: %s\n", bytes_read, sockfd, buffer );
71 |
72 | return true;
73 | }
74 |
75 | void start_conn( int epoll_fd, int num, const char* ip, int port )
76 | {
77 | int ret = 0;
78 | struct sockaddr_in address;
79 | bzero( &address, sizeof( address ) );
80 | address.sin_family = AF_INET;
81 | inet_pton( AF_INET, ip, &address.sin_addr );
82 | address.sin_port = htons( port );
83 |
84 | for ( int i = 0; i < num; ++i )
85 | {
86 | sleep( 0.01 );
87 | int sockfd = socket( PF_INET, SOCK_STREAM, 0 );
88 | printf( "create 1 sock\n" );
89 | if( sockfd < 0 )
90 | {
91 | continue;
92 | }
93 |
94 | if ( connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) ) == 0 )
95 | {
96 | printf( "build connection %d\n", i );
97 | addfd( epoll_fd, sockfd );
98 | }
99 | }
100 | }
101 |
102 | void close_conn( int epoll_fd, int sockfd )
103 | {
104 | epoll_ctl( epoll_fd, EPOLL_CTL_DEL, sockfd, 0 );
105 | close( sockfd );
106 | }
107 |
108 | int main( int argc, char* argv[] )
109 | {
110 | if(argc<4)
111 | {
112 | fprintf(stderr,"usage: %s server_ip server_port client_num ",argv[0]);
113 | exit(0);
114 | }
115 | int epoll_fd = epoll_create( 100 );
116 | start_conn( epoll_fd, atoi( argv[ 3 ] ), argv[1], atoi( argv[2] ) );
117 | epoll_event events[ 10000 ];
118 | char buffer[ 2048 ];
119 | while ( 1 )
120 | {
121 | int fds = epoll_wait( epoll_fd, events, 10000, 2000 );
122 | for ( int i = 0; i < fds; i++ )
123 | {
124 | int sockfd = events[i].data.fd;
125 | if ( events[i].events & EPOLLIN )
126 | {
127 | if ( ! read_once( sockfd, buffer, 2048 ) )
128 | {
129 | close_conn( epoll_fd, sockfd );
130 | }
131 | struct epoll_event event;
132 | event.events = EPOLLOUT | EPOLLET | EPOLLERR;
133 | event.data.fd = sockfd;
134 | epoll_ctl( epoll_fd, EPOLL_CTL_MOD, sockfd, &event );
135 | }
136 | else if( events[i].events & EPOLLOUT )
137 | {
138 | if ( ! write_nbytes( sockfd, request, strlen( request ) ) )
139 | {
140 | close_conn( epoll_fd, sockfd );
141 | }
142 | struct epoll_event event;
143 | event.events = EPOLLIN | EPOLLET | EPOLLERR;
144 | event.data.fd = sockfd;
145 | epoll_ctl( epoll_fd, EPOLL_CTL_MOD, sockfd, &event );
146 | }
147 | else if( events[i].events & EPOLLERR )
148 | {
149 | close_conn( epoll_fd, sockfd );
150 | }
151 | }
152 | }
153 | }
154 |
155 |
--------------------------------------------------------------------------------
/Server/Codes/main.cpp:
--------------------------------------------------------------------------------
1 | #include"web_thread.h"
2 | #include"web_function.h"
3 | #include"http_conn.h"
4 |
5 | using namespace std;
6 |
7 | webthread* thread_ptr;//指向自定义线程类的指针,这是一个全局变量,主线程和子线程通过线程类的双向管道来实现通信
8 |
9 | int sig_pipefd[2];//系统中断信号处理函数与主函数之间的通信管道,本程序把信号处理放在主函数中进行
10 |
11 |
12 |
13 | void* thread(void* arg)//子线程主函数
14 | {
15 | int* p=(int*)arg;
16 | int index=*p;
17 | delete arg;
18 |
19 | thread_ptr[index].work();//对应的子线程开始工作
20 | }
21 |
22 | void create_son_thread()//创建子线程
23 | {
24 | pthread_t tid;
25 | printf( "create son threads now\n" );
26 | for(int i=0;i[thread_num];
130 | webthread::listenfd=listenfd;
131 |
132 | pthread_mutex_init(&mutex_conn,NULL);
133 |
134 | create_son_thread();//创建子线程,子线程开始运行
135 |
136 | int epollfd = epoll_create( 5 );
137 | assert( epollfd != -1 );
138 |
139 | addfd(epollfd,listenfd,true);
140 | webthread::m_epollfd=epollfd;
141 |
142 |
143 |
144 | int ret = socketpair( PF_UNIX, SOCK_STREAM, 0, sig_pipefd );//创建信号处理函数与主函数之间的通信管道
145 | assert( ret != -1 );
146 |
147 | setnonblocking( sig_pipefd[1] );
148 | addfd( epollfd, sig_pipefd[0] );
149 |
150 |
151 | addsig( SIGTERM, sig_handler );
152 | addsig( SIGINT, sig_handler );
153 | addsig( SIGALRM,sig_handler );
154 | addsig( SIGPIPE, SIG_IGN );
155 |
156 | epoll_event events[MAX_EVENT_NUM];
157 |
158 |
159 | int m_pid=(int)getpid();
160 | printf("PID: %d\n",m_pid);
161 | printf("server start\n");
162 | alarm(ALARM_TIME);//开始定时
163 |
164 | bool stop=false;
165 | int thread_index=0;
166 |
167 | while(!stop)
168 | {
169 | int number=epoll_wait(epollfd,events,MAX_EVENT_NUM,-1);
170 | if(number<0 && errno!=EINTR)
171 | {
172 | close_son_thread();
173 | unix_error("main thread epoll failed.");
174 | break;
175 | }
176 |
177 | for(int i=0;i
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 | #include
24 | #include
25 |
26 |
27 | const int thread_num=4;//线程数量
28 | #define LISTENQ 1024//listen()函数的参数
29 | #define MAX_EVENT_NUM 65535//epoll_event的事件数
30 | #define EVENT_TABLE_SIZE 4096//epoll_wait()的参数
31 | #define NEW_CONN '0'//发送给子线程的信号,表示有新连接到来
32 | #define CLOSE_DEAD_CONN '1'//发送给子线程的信号,表示关闭空闲的长连接
33 | #define CLOSE_THREAD '2'//发送给子线程的信号,表示结束子线程
34 | #define ALARM_TIME 30//定时时间,也是长连接的超时时间
35 | #define USER_PER_THREAD 500//每个子线程的最大用户数
36 |
37 | #define FILENAME_LEN 200//文件名称的最大长度
38 | #define READ_BUFFER_SIZE 256//给每个用户分配的读缓冲区大小
39 | #define WRITE_BUFFER_SIZE 256//给每个用户分配的写缓冲区大小
40 |
41 |
42 | pthread_mutex_t mutex_conn;
43 |
44 |
45 | static std::atomic user_count(0);//C++11的原子变量,统计所有线程的当前活跃用户数
46 | static std::atomic max_user_online(0);
47 |
48 |
49 | void unix_error(char *msg) /* Unix-style error */
50 | {
51 | fprintf(stderr,"%s: %s\n", msg, strerror(errno));
52 | exit(0);
53 | }
54 |
55 | void app_error(char *msg) /* Application error */
56 | {
57 | fprintf(stderr, "%s\n", msg);
58 | exit(0);
59 | }
60 |
61 | void show_error(char *msg)
62 | {
63 | fprintf(stderr, "%s: %s\n", msg, strerror(errno));
64 | }
65 |
66 | void show_addr(sockaddr_in address)
67 | {
68 | int save_errno=errno;
69 | char host[NI_MAXHOST];
70 | char service[NI_MAXSERV];
71 | socklen_t addrlength = sizeof(address );
72 |
73 | int ret=getnameinfo((struct sockaddr *)(&address), sizeof(struct sockaddr),host, sizeof(host), service, sizeof(service),NI_NUMERICHOST|NI_NUMERICSERV);
74 | if(ret!=0)
75 | {
76 | show_error("address changed failed");
77 | }
78 | else
79 | {
80 | printf("(%s: %s)\n",host,service);
81 | }
82 | errno=save_errno;
83 |
84 | }
85 |
86 | int Open(const char *pathname, int flags, mode_t mode)
87 | {
88 | int rc;
89 |
90 | if ((rc = open(pathname, flags, mode)) < 0)
91 | unix_error("Open error");
92 | return rc;
93 | }
94 |
95 | ssize_t Read(int fd, void *buf, size_t count)
96 | {
97 | ssize_t rc;
98 |
99 | if ((rc = read(fd, buf, count)) < 0)
100 | unix_error("Read error");
101 | return rc;
102 | }
103 |
104 | ssize_t Write(int fd, const void *buf, size_t count)
105 | {
106 | ssize_t rc;
107 |
108 | if ((rc = write(fd, buf, count)) < 0)
109 | unix_error("Write error");
110 | return rc;
111 | }
112 |
113 |
114 | void Close(int fd)
115 | {
116 | int rc;
117 |
118 | if ((rc = close(fd)) < 0)
119 | unix_error("Close error");
120 | }
121 |
122 |
123 | static int setnonblocking( int fd )
124 | {
125 | int old_option = fcntl( fd, F_GETFL );
126 | int new_option = old_option | O_NONBLOCK;
127 | fcntl( fd, F_SETFL, new_option );
128 | return old_option;
129 | }
130 |
131 |
132 | static void removefd( int epollfd, int fd )//删除事件
133 | {
134 | epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 );
135 | Close( fd );
136 | }
137 |
138 | static void addfd( int epollfd, int fd )//添加事件
139 | {
140 | epoll_event event;
141 | event.data.fd = fd;
142 | event.events = EPOLLIN | EPOLLET;
143 | epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
144 | setnonblocking( fd );
145 | }
146 |
147 | void addfd( int epollfd, int fd, bool one_shot )//添加事件
148 | {
149 | epoll_event event;
150 | event.data.fd = fd;
151 | event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
152 | if( one_shot )
153 | {
154 | event.events |= EPOLLONESHOT;
155 | }
156 | epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
157 | setnonblocking( fd );
158 | }
159 |
160 | void modfd( int epollfd, int fd, int ev )//修改事件
161 | {
162 | epoll_event event;
163 | event.data.fd = fd;
164 | event.events = ev | EPOLLET | EPOLLONESHOT | EPOLLRDHUP;
165 | epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );
166 | }
167 |
168 | void show_sys_time()
169 | {
170 |
171 | time_t timel;
172 | time(&timel);
173 | printf("time: %s",asctime(gmtime(&timel)));
174 | }
175 |
176 | static void addsig( int sig, void( handler )(int), bool restart = true )
177 | {
178 | struct sigaction sa;
179 | memset( &sa, '\0', sizeof( sa ) );
180 | sa.sa_handler = handler;
181 | if( restart )
182 | {
183 | sa.sa_flags |= SA_RESTART;
184 | }
185 | sigfillset( &sa.sa_mask );
186 | assert( sigaction( sig, &sa, NULL ) != -1 );
187 | }
188 |
189 | int open_clientfd(char *ip, char *_port) {
190 |
191 | int port=atoi(_port);
192 |
193 | struct sockaddr_in address;
194 | bzero( &address, sizeof( address ) );
195 | address.sin_family = AF_INET;
196 | inet_pton( AF_INET, ip, &address.sin_addr );
197 | address.sin_port = htons( port );
198 |
199 | int fd=socket(AF_INET,SOCK_STREAM,0);
200 |
201 | int ret=connect(fd,(struct sockaddr*)&address,sizeof(address));
202 | if(ret<0)
203 | {
204 | app_error("server connected failed");
205 | }
206 | else
207 | {
208 | return fd;
209 | }
210 | }
211 |
212 | int open_listenfd(char *ip, char *_port,int backlog)//仅ipv4
213 | {
214 | int port=atoi(_port);
215 |
216 | struct sockaddr_in address;
217 | bzero( &address, sizeof( address ) );
218 | address.sin_family = AF_INET;
219 | inet_pton( AF_INET, ip, &address.sin_addr );
220 | address.sin_port = htons( port );
221 |
222 | int fd=socket(AF_INET,SOCK_STREAM,0);
223 |
224 | int ret=bind(fd,(struct sockaddr*)&address,sizeof(address));
225 | assert(ret!=-1);
226 |
227 | ret=listen(fd,backlog);
228 | if(ret<0)
229 | {
230 | unix_error("listenfd opened failed.");
231 | }
232 | else
233 | {
234 | return fd;
235 | }
236 |
237 | }
238 |
239 | int open_listenfd(char *port)//ipv4/ipv6通用
240 | {
241 | struct addrinfo hints, *listp, *p;
242 | int listenfd, rc, optval=1;
243 |
244 | /* Get a list of potential server addresses */
245 | memset(&hints, 0, sizeof(struct addrinfo));
246 | hints.ai_socktype = SOCK_STREAM; /* Accept connections */
247 | hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* ... on any IP address */
248 | hints.ai_flags |= AI_NUMERICSERV; /* ... using port number */
249 | if ((rc = getaddrinfo(NULL, port, &hints, &listp)) != 0) {
250 | fprintf(stderr, "getaddrinfo failed (port %s): %s\n", port, gai_strerror(rc));
251 | return -2;
252 | }
253 |
254 | /* Walk the list for one that we can bind to */
255 | for (p = listp; p; p = p->ai_next) {
256 | /* Create a socket descriptor */
257 | if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
258 | continue; /* Socket failed, try the next */
259 |
260 | /* Eliminates "Address already in use" error from bind */
261 | setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, //line:netp:csapp:setsockopt
262 | (const void *)&optval , sizeof(int));
263 |
264 | /* Bind the descriptor to the address */
265 | if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0)
266 | break; /* Success */
267 | if (close(listenfd) < 0) { /* Bind failed, try the next */
268 | fprintf(stderr, "open_listenfd close failed: %s\n", strerror(errno));
269 | return -1;
270 | }
271 | }
272 |
273 |
274 | /* Clean up */
275 | freeaddrinfo(listp);
276 | if (!p) /* No address worked */
277 | return -1;
278 |
279 | /* Make it a listening socket ready to accept connection requests */
280 | if (listen(listenfd, LISTENQ) < 0) {
281 | close(listenfd);
282 | return -1;
283 | }
284 | return listenfd;
285 | }
286 |
287 |
288 | #endif // WEB_FUNCTION
289 |
290 |
--------------------------------------------------------------------------------
/Client/Debug/Makefile:
--------------------------------------------------------------------------------
1 | #############################################################################
2 | # Makefile for building: client
3 | # Generated by qmake (2.01a) (Qt 4.8.7) on: ?? 2? 27 15:14:57 2020
4 | # Project: ../Codes/client.pro
5 | # Template: app
6 | # Command: /usr/lib/x86_64-linux-gnu/qt4/bin/qmake -spec /usr/share/qt4/mkspecs/linux-g++-64 CONFIG+=debug -o Makefile ../Codes/client.pro
7 | #############################################################################
8 |
9 | ####### Compiler, tools and options
10 |
11 | CC = gcc
12 | CXX = g++
13 | DEFINES = -DQT_CORE_LIB -DQT_SHARED
14 | CFLAGS = -m64 -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
15 | CXXFLAGS = -m64 -pipe -std=c++11 -g -Wall -W -D_REENTRANT $(DEFINES)
16 | INCPATH = -I/usr/share/qt4/mkspecs/linux-g++-64 -I../Codes -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -I../Codes -I.
17 | LINK = g++
18 | LFLAGS = -m64
19 | LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -lQtCore -lpthread
20 | AR = ar cqs
21 | RANLIB =
22 | QMAKE = /usr/lib/x86_64-linux-gnu/qt4/bin/qmake
23 | TAR = tar -cf
24 | COMPRESS = gzip -9f
25 | COPY = cp -f
26 | SED = sed
27 | COPY_FILE = $(COPY)
28 | COPY_DIR = $(COPY) -r
29 | STRIP = strip
30 | INSTALL_FILE = install -m 644 -p
31 | INSTALL_DIR = $(COPY_DIR)
32 | INSTALL_PROGRAM = install -m 755 -p
33 | DEL_FILE = rm -f
34 | SYMLINK = ln -f -s
35 | DEL_DIR = rmdir
36 | MOVE = mv -f
37 | CHK_DIR_EXISTS= test -d
38 | MKDIR = mkdir -p
39 |
40 | ####### Output directory
41 |
42 | OBJECTS_DIR = ./
43 |
44 | ####### Files
45 |
46 | SOURCES = ../Codes/main.cpp
47 | OBJECTS = main.o
48 | DIST = /usr/share/qt4/mkspecs/common/unix.conf \
49 | /usr/share/qt4/mkspecs/common/linux.conf \
50 | /usr/share/qt4/mkspecs/common/gcc-base.conf \
51 | /usr/share/qt4/mkspecs/common/gcc-base-unix.conf \
52 | /usr/share/qt4/mkspecs/common/g++-base.conf \
53 | /usr/share/qt4/mkspecs/common/g++-unix.conf \
54 | /usr/share/qt4/mkspecs/qconfig.pri \
55 | /usr/share/qt4/mkspecs/features/qt_functions.prf \
56 | /usr/share/qt4/mkspecs/features/qt_config.prf \
57 | /usr/share/qt4/mkspecs/features/exclusive_builds.prf \
58 | /usr/share/qt4/mkspecs/features/default_pre.prf \
59 | /usr/share/qt4/mkspecs/features/debug.prf \
60 | /usr/share/qt4/mkspecs/features/default_post.prf \
61 | /usr/share/qt4/mkspecs/features/shared.prf \
62 | /usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \
63 | /usr/share/qt4/mkspecs/features/warn_on.prf \
64 | /usr/share/qt4/mkspecs/features/qt.prf \
65 | /usr/share/qt4/mkspecs/features/unix/thread.prf \
66 | /usr/share/qt4/mkspecs/features/moc.prf \
67 | /usr/share/qt4/mkspecs/features/resources.prf \
68 | /usr/share/qt4/mkspecs/features/uic.prf \
69 | /usr/share/qt4/mkspecs/features/yacc.prf \
70 | /usr/share/qt4/mkspecs/features/lex.prf \
71 | /usr/share/qt4/mkspecs/features/include_source_dir.prf \
72 | ../Codes/client.pro
73 | QMAKE_TARGET = client
74 | DESTDIR =
75 | TARGET = client
76 |
77 | first: all
78 | ####### Implicit rules
79 |
80 | .SUFFIXES: .o .c .cpp .cc .cxx .C
81 |
82 | .cpp.o:
83 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
84 |
85 | .cc.o:
86 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
87 |
88 | .cxx.o:
89 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
90 |
91 | .C.o:
92 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
93 |
94 | .c.o:
95 | $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
96 |
97 | ####### Build rules
98 |
99 | all: Makefile $(TARGET)
100 |
101 | $(TARGET): $(OBJECTS)
102 | $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
103 | { test -n "$(DESTDIR)" && DESTDIR="$(DESTDIR)" || DESTDIR=.; } && test $$(gdb --version | sed -e 's,[^0-9][^0-9]*\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $$DESTDIR" -ex quit '$(TARGET)' && test -f $(TARGET).gdb-index && objcopy --add-section '.gdb_index=$(TARGET).gdb-index' --set-section-flags '.gdb_index=readonly' '$(TARGET)' '$(TARGET)' && rm -f $(TARGET).gdb-index || true
104 |
105 | Makefile: ../Codes/client.pro /usr/share/qt4/mkspecs/linux-g++-64/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \
106 | /usr/share/qt4/mkspecs/common/linux.conf \
107 | /usr/share/qt4/mkspecs/common/gcc-base.conf \
108 | /usr/share/qt4/mkspecs/common/gcc-base-unix.conf \
109 | /usr/share/qt4/mkspecs/common/g++-base.conf \
110 | /usr/share/qt4/mkspecs/common/g++-unix.conf \
111 | /usr/share/qt4/mkspecs/qconfig.pri \
112 | /usr/share/qt4/mkspecs/features/qt_functions.prf \
113 | /usr/share/qt4/mkspecs/features/qt_config.prf \
114 | /usr/share/qt4/mkspecs/features/exclusive_builds.prf \
115 | /usr/share/qt4/mkspecs/features/default_pre.prf \
116 | /usr/share/qt4/mkspecs/features/debug.prf \
117 | /usr/share/qt4/mkspecs/features/default_post.prf \
118 | /usr/share/qt4/mkspecs/features/shared.prf \
119 | /usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \
120 | /usr/share/qt4/mkspecs/features/warn_on.prf \
121 | /usr/share/qt4/mkspecs/features/qt.prf \
122 | /usr/share/qt4/mkspecs/features/unix/thread.prf \
123 | /usr/share/qt4/mkspecs/features/moc.prf \
124 | /usr/share/qt4/mkspecs/features/resources.prf \
125 | /usr/share/qt4/mkspecs/features/uic.prf \
126 | /usr/share/qt4/mkspecs/features/yacc.prf \
127 | /usr/share/qt4/mkspecs/features/lex.prf \
128 | /usr/share/qt4/mkspecs/features/include_source_dir.prf \
129 | /usr/lib/x86_64-linux-gnu/libQtCore.prl
130 | $(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++-64 CONFIG+=debug -o Makefile ../Codes/client.pro
131 | /usr/share/qt4/mkspecs/common/unix.conf:
132 | /usr/share/qt4/mkspecs/common/linux.conf:
133 | /usr/share/qt4/mkspecs/common/gcc-base.conf:
134 | /usr/share/qt4/mkspecs/common/gcc-base-unix.conf:
135 | /usr/share/qt4/mkspecs/common/g++-base.conf:
136 | /usr/share/qt4/mkspecs/common/g++-unix.conf:
137 | /usr/share/qt4/mkspecs/qconfig.pri:
138 | /usr/share/qt4/mkspecs/features/qt_functions.prf:
139 | /usr/share/qt4/mkspecs/features/qt_config.prf:
140 | /usr/share/qt4/mkspecs/features/exclusive_builds.prf:
141 | /usr/share/qt4/mkspecs/features/default_pre.prf:
142 | /usr/share/qt4/mkspecs/features/debug.prf:
143 | /usr/share/qt4/mkspecs/features/default_post.prf:
144 | /usr/share/qt4/mkspecs/features/shared.prf:
145 | /usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf:
146 | /usr/share/qt4/mkspecs/features/warn_on.prf:
147 | /usr/share/qt4/mkspecs/features/qt.prf:
148 | /usr/share/qt4/mkspecs/features/unix/thread.prf:
149 | /usr/share/qt4/mkspecs/features/moc.prf:
150 | /usr/share/qt4/mkspecs/features/resources.prf:
151 | /usr/share/qt4/mkspecs/features/uic.prf:
152 | /usr/share/qt4/mkspecs/features/yacc.prf:
153 | /usr/share/qt4/mkspecs/features/lex.prf:
154 | /usr/share/qt4/mkspecs/features/include_source_dir.prf:
155 | /usr/lib/x86_64-linux-gnu/libQtCore.prl:
156 | qmake: FORCE
157 | @$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++-64 CONFIG+=debug -o Makefile ../Codes/client.pro
158 |
159 | dist:
160 | @$(CHK_DIR_EXISTS) .tmp/client1.0.0 || $(MKDIR) .tmp/client1.0.0
161 | $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/client1.0.0/ && $(COPY_FILE) --parents ../Codes/main.cpp .tmp/client1.0.0/ && (cd `dirname .tmp/client1.0.0` && $(TAR) client1.0.0.tar client1.0.0 && $(COMPRESS) client1.0.0.tar) && $(MOVE) `dirname .tmp/client1.0.0`/client1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/client1.0.0
162 |
163 |
164 | clean:compiler_clean
165 | -$(DEL_FILE) $(OBJECTS)
166 | -$(DEL_FILE) *~ core *.core
167 |
168 |
169 | ####### Sub-libraries
170 |
171 | distclean: clean
172 | -$(DEL_FILE) $(TARGET)
173 | -$(DEL_FILE) Makefile
174 |
175 |
176 | check: first
177 |
178 | mocclean: compiler_moc_header_clean compiler_moc_source_clean
179 |
180 | mocables: compiler_moc_header_make_all compiler_moc_source_make_all
181 |
182 | compiler_moc_header_make_all:
183 | compiler_moc_header_clean:
184 | compiler_rcc_make_all:
185 | compiler_rcc_clean:
186 | compiler_image_collection_make_all: qmake_image_collection.cpp
187 | compiler_image_collection_clean:
188 | -$(DEL_FILE) qmake_image_collection.cpp
189 | compiler_moc_source_make_all:
190 | compiler_moc_source_clean:
191 | compiler_uic_make_all:
192 | compiler_uic_clean:
193 | compiler_yacc_decl_make_all:
194 | compiler_yacc_decl_clean:
195 | compiler_yacc_impl_make_all:
196 | compiler_yacc_impl_clean:
197 | compiler_lex_make_all:
198 | compiler_lex_clean:
199 | compiler_clean:
200 |
201 | ####### Compile
202 |
203 | main.o: ../Codes/main.cpp
204 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o ../Codes/main.cpp
205 |
206 | ####### Install
207 |
208 | install: FORCE
209 |
210 | uninstall: FORCE
211 |
212 | FORCE:
213 |
214 |
--------------------------------------------------------------------------------
/Server/Debug/Makefile:
--------------------------------------------------------------------------------
1 | #############################################################################
2 | # Makefile for building: server
3 | # Generated by qmake (2.01a) (Qt 4.8.7) on: ?? 3? 28 13:48:52 2020
4 | # Project: ../Codes/server.pro
5 | # Template: app
6 | # Command: /usr/lib/x86_64-linux-gnu/qt4/bin/qmake -spec /usr/share/qt4/mkspecs/linux-g++-64 CONFIG+=debug -o Makefile ../Codes/server.pro
7 | #############################################################################
8 |
9 | ####### Compiler, tools and options
10 |
11 | CC = gcc
12 | CXX = g++
13 | DEFINES = -DQT_CORE_LIB -DQT_SHARED
14 | CFLAGS = -m64 -pipe -g -Wall -W -D_REENTRANT $(DEFINES)
15 | CXXFLAGS = -m64 -pipe -std=c++0x -g -Wall -W -D_REENTRANT $(DEFINES)
16 | INCPATH = -I/usr/share/qt4/mkspecs/linux-g++-64 -I../Codes -I/usr/include/qt4/QtCore -I/usr/include/qt4 -I. -I../Codes -I.
17 | LINK = g++
18 | LFLAGS = -m64
19 | LIBS = $(SUBLIBS) -L/usr/lib/x86_64-linux-gnu -lQtCore -lpthread
20 | AR = ar cqs
21 | RANLIB =
22 | QMAKE = /usr/lib/x86_64-linux-gnu/qt4/bin/qmake
23 | TAR = tar -cf
24 | COMPRESS = gzip -9f
25 | COPY = cp -f
26 | SED = sed
27 | COPY_FILE = $(COPY)
28 | COPY_DIR = $(COPY) -r
29 | STRIP = strip
30 | INSTALL_FILE = install -m 644 -p
31 | INSTALL_DIR = $(COPY_DIR)
32 | INSTALL_PROGRAM = install -m 755 -p
33 | DEL_FILE = rm -f
34 | SYMLINK = ln -f -s
35 | DEL_DIR = rmdir
36 | MOVE = mv -f
37 | CHK_DIR_EXISTS= test -d
38 | MKDIR = mkdir -p
39 |
40 | ####### Output directory
41 |
42 | OBJECTS_DIR = ./
43 |
44 | ####### Files
45 |
46 | SOURCES = ../Codes/main.cpp
47 | OBJECTS = main.o
48 | DIST = /usr/share/qt4/mkspecs/common/unix.conf \
49 | /usr/share/qt4/mkspecs/common/linux.conf \
50 | /usr/share/qt4/mkspecs/common/gcc-base.conf \
51 | /usr/share/qt4/mkspecs/common/gcc-base-unix.conf \
52 | /usr/share/qt4/mkspecs/common/g++-base.conf \
53 | /usr/share/qt4/mkspecs/common/g++-unix.conf \
54 | /usr/share/qt4/mkspecs/qconfig.pri \
55 | /usr/share/qt4/mkspecs/features/qt_functions.prf \
56 | /usr/share/qt4/mkspecs/features/qt_config.prf \
57 | /usr/share/qt4/mkspecs/features/exclusive_builds.prf \
58 | /usr/share/qt4/mkspecs/features/default_pre.prf \
59 | /usr/share/qt4/mkspecs/features/debug.prf \
60 | /usr/share/qt4/mkspecs/features/default_post.prf \
61 | /usr/share/qt4/mkspecs/features/shared.prf \
62 | /usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \
63 | /usr/share/qt4/mkspecs/features/warn_on.prf \
64 | /usr/share/qt4/mkspecs/features/qt.prf \
65 | /usr/share/qt4/mkspecs/features/unix/thread.prf \
66 | /usr/share/qt4/mkspecs/features/moc.prf \
67 | /usr/share/qt4/mkspecs/features/resources.prf \
68 | /usr/share/qt4/mkspecs/features/uic.prf \
69 | /usr/share/qt4/mkspecs/features/yacc.prf \
70 | /usr/share/qt4/mkspecs/features/lex.prf \
71 | /usr/share/qt4/mkspecs/features/include_source_dir.prf \
72 | ../Codes/server.pro
73 | QMAKE_TARGET = server
74 | DESTDIR =
75 | TARGET = server
76 |
77 | first: all
78 | ####### Implicit rules
79 |
80 | .SUFFIXES: .o .c .cpp .cc .cxx .C
81 |
82 | .cpp.o:
83 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
84 |
85 | .cc.o:
86 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
87 |
88 | .cxx.o:
89 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
90 |
91 | .C.o:
92 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
93 |
94 | .c.o:
95 | $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
96 |
97 | ####### Build rules
98 |
99 | all: Makefile $(TARGET)
100 |
101 | $(TARGET): $(OBJECTS)
102 | $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
103 | { test -n "$(DESTDIR)" && DESTDIR="$(DESTDIR)" || DESTDIR=.; } && test $$(gdb --version | sed -e 's,[^0-9][^0-9]*\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $$DESTDIR" -ex quit '$(TARGET)' && test -f $(TARGET).gdb-index && objcopy --add-section '.gdb_index=$(TARGET).gdb-index' --set-section-flags '.gdb_index=readonly' '$(TARGET)' '$(TARGET)' && rm -f $(TARGET).gdb-index || true
104 |
105 | Makefile: ../Codes/server.pro /usr/share/qt4/mkspecs/linux-g++-64/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \
106 | /usr/share/qt4/mkspecs/common/linux.conf \
107 | /usr/share/qt4/mkspecs/common/gcc-base.conf \
108 | /usr/share/qt4/mkspecs/common/gcc-base-unix.conf \
109 | /usr/share/qt4/mkspecs/common/g++-base.conf \
110 | /usr/share/qt4/mkspecs/common/g++-unix.conf \
111 | /usr/share/qt4/mkspecs/qconfig.pri \
112 | /usr/share/qt4/mkspecs/features/qt_functions.prf \
113 | /usr/share/qt4/mkspecs/features/qt_config.prf \
114 | /usr/share/qt4/mkspecs/features/exclusive_builds.prf \
115 | /usr/share/qt4/mkspecs/features/default_pre.prf \
116 | /usr/share/qt4/mkspecs/features/debug.prf \
117 | /usr/share/qt4/mkspecs/features/default_post.prf \
118 | /usr/share/qt4/mkspecs/features/shared.prf \
119 | /usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf \
120 | /usr/share/qt4/mkspecs/features/warn_on.prf \
121 | /usr/share/qt4/mkspecs/features/qt.prf \
122 | /usr/share/qt4/mkspecs/features/unix/thread.prf \
123 | /usr/share/qt4/mkspecs/features/moc.prf \
124 | /usr/share/qt4/mkspecs/features/resources.prf \
125 | /usr/share/qt4/mkspecs/features/uic.prf \
126 | /usr/share/qt4/mkspecs/features/yacc.prf \
127 | /usr/share/qt4/mkspecs/features/lex.prf \
128 | /usr/share/qt4/mkspecs/features/include_source_dir.prf \
129 | /usr/lib/x86_64-linux-gnu/libQtCore.prl
130 | $(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++-64 CONFIG+=debug -o Makefile ../Codes/server.pro
131 | /usr/share/qt4/mkspecs/common/unix.conf:
132 | /usr/share/qt4/mkspecs/common/linux.conf:
133 | /usr/share/qt4/mkspecs/common/gcc-base.conf:
134 | /usr/share/qt4/mkspecs/common/gcc-base-unix.conf:
135 | /usr/share/qt4/mkspecs/common/g++-base.conf:
136 | /usr/share/qt4/mkspecs/common/g++-unix.conf:
137 | /usr/share/qt4/mkspecs/qconfig.pri:
138 | /usr/share/qt4/mkspecs/features/qt_functions.prf:
139 | /usr/share/qt4/mkspecs/features/qt_config.prf:
140 | /usr/share/qt4/mkspecs/features/exclusive_builds.prf:
141 | /usr/share/qt4/mkspecs/features/default_pre.prf:
142 | /usr/share/qt4/mkspecs/features/debug.prf:
143 | /usr/share/qt4/mkspecs/features/default_post.prf:
144 | /usr/share/qt4/mkspecs/features/shared.prf:
145 | /usr/share/qt4/mkspecs/features/unix/gdb_dwarf_index.prf:
146 | /usr/share/qt4/mkspecs/features/warn_on.prf:
147 | /usr/share/qt4/mkspecs/features/qt.prf:
148 | /usr/share/qt4/mkspecs/features/unix/thread.prf:
149 | /usr/share/qt4/mkspecs/features/moc.prf:
150 | /usr/share/qt4/mkspecs/features/resources.prf:
151 | /usr/share/qt4/mkspecs/features/uic.prf:
152 | /usr/share/qt4/mkspecs/features/yacc.prf:
153 | /usr/share/qt4/mkspecs/features/lex.prf:
154 | /usr/share/qt4/mkspecs/features/include_source_dir.prf:
155 | /usr/lib/x86_64-linux-gnu/libQtCore.prl:
156 | qmake: FORCE
157 | @$(QMAKE) -spec /usr/share/qt4/mkspecs/linux-g++-64 CONFIG+=debug -o Makefile ../Codes/server.pro
158 |
159 | dist:
160 | @$(CHK_DIR_EXISTS) .tmp/server1.0.0 || $(MKDIR) .tmp/server1.0.0
161 | $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/server1.0.0/ && $(COPY_FILE) --parents ../Codes/http_conn.h ../Codes/web_function.h ../Codes/web_thread.h .tmp/server1.0.0/ && $(COPY_FILE) --parents ../Codes/main.cpp .tmp/server1.0.0/ && (cd `dirname .tmp/server1.0.0` && $(TAR) server1.0.0.tar server1.0.0 && $(COMPRESS) server1.0.0.tar) && $(MOVE) `dirname .tmp/server1.0.0`/server1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/server1.0.0
162 |
163 |
164 | clean:compiler_clean
165 | -$(DEL_FILE) $(OBJECTS)
166 | -$(DEL_FILE) *~ core *.core
167 |
168 |
169 | ####### Sub-libraries
170 |
171 | distclean: clean
172 | -$(DEL_FILE) $(TARGET)
173 | -$(DEL_FILE) Makefile
174 |
175 |
176 | check: first
177 |
178 | mocclean: compiler_moc_header_clean compiler_moc_source_clean
179 |
180 | mocables: compiler_moc_header_make_all compiler_moc_source_make_all
181 |
182 | compiler_moc_header_make_all:
183 | compiler_moc_header_clean:
184 | compiler_rcc_make_all:
185 | compiler_rcc_clean:
186 | compiler_image_collection_make_all: qmake_image_collection.cpp
187 | compiler_image_collection_clean:
188 | -$(DEL_FILE) qmake_image_collection.cpp
189 | compiler_moc_source_make_all:
190 | compiler_moc_source_clean:
191 | compiler_uic_make_all:
192 | compiler_uic_clean:
193 | compiler_yacc_decl_make_all:
194 | compiler_yacc_decl_clean:
195 | compiler_yacc_impl_make_all:
196 | compiler_yacc_impl_clean:
197 | compiler_lex_make_all:
198 | compiler_lex_clean:
199 | compiler_clean:
200 |
201 | ####### Compile
202 |
203 | main.o: ../Codes/main.cpp ../Codes/web_thread.h \
204 | ../Codes/http_conn.h \
205 | ../Codes/web_function.h
206 | $(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o ../Codes/main.cpp
207 |
208 | ####### Install
209 |
210 | install: FORCE
211 |
212 | uninstall: FORCE
213 |
214 | FORCE:
215 |
216 |
--------------------------------------------------------------------------------
/Server/Codes/web_thread.h:
--------------------------------------------------------------------------------
1 | #ifndef WEB_THREAD_H
2 | #define WEB_THREAD_H
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