HTTP报文结构
请求报文
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63//client #include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <sys/socket.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> void show_info(int connfd){ struct sockaddr_in local_addr; bzero(&local_addr,sizeof(local_addr)); socklen_t local_addr_len = sizeof(local_addr); getsockname(connfd,(struct sockaddr*)&local_addr,&local_addr_len); printf("client local %s:%dn", inet_ntoa(local_addr.sin_addr),ntohs(local_addr.sin_port)); struct sockaddr_in peer_addr; bzero(&peer_addr,sizeof(peer_addr)); socklen_t peer_addr_len = sizeof(peer_addr); getpeername(connfd,(struct sockaddr*)&peer_addr,&peer_addr_len); printf("clinet peer%s:%dn", inet_ntoa(peer_addr.sin_addr),ntohs(peer_addr.sin_port)); } int main(int argc,char* argv[]){ if(3 != argc){ printf("usage:%s <ip> <#port> n",argv[0]); return 1; } //建立套接字 int connfd = socket(AF_INET,SOCK_STREAM,0); if(-1 == connfd){ perror("socket err"); return 1; } struct sockaddr_in remote_addr; bzero(&remote_addr,sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_addr.s_addr = inet_addr(argv[1]); remote_addr.sin_port = htons(atoi(argv[2])); //连接到远方主机端口 if(-1 == connect(connfd,(struct sockaddr*)&remote_addr,sizeof(remote_addr))){ perror("connect err"); return 1; } show_info(connfd); char buf[BUFSIZ]; bzero(buf,BUFSIZ); while(fgets(buf,BUFSIZ,stdin) != NULL){ write(connfd,buf,strlen(buf)+1); printf("client send:%sn",buf); bzero(buf,BUFSIZ); // sendfile(fd,connfd,NULL,); if(-1 == read(connfd,buf,BUFSIZ)){ perror("read err"); return 1; } printf("client recv:%sn",buf); } close(connfd); }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277//server #include <arpa/inet.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/sendfile.h> #include <signal.h> #include <sys/wait.h> #include <pthread.h> #include <string> #include <iostream> #include <sstream> #include<sys/poll.h> #include<linux/fs.h> using namespace std; struct func_t_arg { struct pollfd* poll_fd; int i; int poll_fd_cnt; char* work_dir; }; class ThreadPool { typedef void (*func_t)(struct pollfd* poll_fd,int i,int poll_fd_cnt,const char* work_dir); public: ThreadPool(size_t count):destroy(false) { // 初始化互斥锁和条件变量 pthread_mutex_init(&mutex,NULL); pthread_cond_init(&cond,NULL); // 初始化线程组 for(int i=0; i<count; i++) { pthread_t tid; pthread_create(&tid,NULL,reinterpret_cast<void*(*)(void*)>(&ThreadPool::Route),this); threads.push_back(tid); } } ~ThreadPool() { // 通知线程退出 destroy = true; //让阻塞的线程不再阻塞,pthread_join是等待回收线程的。 pthread_cond_broadcast(&cond); for(vector<pthread_t>::iterator it = threads.begin(); it != threads.end(); it++) { pthread_join(*it,NULL); } // 销毁互斥锁和条件变量 pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); } void AddJob(func_t func,struct func_t_arg arg) { pthread_mutex_lock(&mutex); tasks.push(func); args.push(arg); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); } private: static void Route(ThreadPool* pPool) { for(;;) { pthread_mutex_lock(&(pPool->mutex)); // 如果没有任务等待 while(pPool->tasks.empty() && !pPool->destroy) { pthread_cond_wait(&(pPool->cond),&(pPool->mutex)); } // 线程退出 if(pPool->destroy) { pthread_mutex_unlock(&(pPool->mutex)); break; } // 获取任务 func_t task = pPool->tasks.front(); pPool->tasks.pop(); struct func_t_arg arg = pPool->args.front(); pPool->args.pop(); pthread_mutex_unlock(&(pPool->mutex)); // 执行任务 task(arg.poll_fd,arg.i,arg.poll_fd_cnt,arg.work_dir); } } private: vector<pthread_t> threads; ///< 线程组 queue<func_t> tasks; ///< 任务队列 queue<struct func_t_arg> args; ///< 参数队列 pthread_mutex_t mutex; pthread_cond_t cond; bool destroy; ///< 线程池销毁标志 }; //char* work_dir = NULL; //struct pollfd poll_fd[INR_OPEN_MAX]; void show_info(int connfd) { struct sockaddr_in local_addr; bzero(&local_addr,sizeof(local_addr)); socklen_t local_addr_len = sizeof(local_addr); getsockname(connfd,(struct sockaddr*)&local_addr,&local_addr_len); printf("server local %s:%dn",inet_ntoa(local_addr.sin_addr),ntohs(local_addr.sin_port)); struct sockaddr_in peer_addr; bzero(&peer_addr,sizeof(peer_addr)); socklen_t peer_addr_len = sizeof(peer_addr); getpeername(connfd,(struct sockaddr*)&peer_addr,&peer_addr_len); printf("server peer %s:%dn",inet_ntoa(peer_addr.sin_addr),ntohs(peer_addr.sin_port)); } void Handle(struct pollfd* poll_fd,int i,int poll_fd_cnt,const char* work_dir) { char buf[BUFSIZ]; for(;;) { bzero(buf,BUFSIZ); ssize_t len; if((len = read(poll_fd[i].fd,buf,BUFSIZ-1)) == -1) { perror("read err"); pthread_exit((void*)1); } if(0 == len) { printf("close %dn",poll_fd[i].fd); printf("%d vs %dn",poll_fd[i].revents,poll_fd[i].revents); close(poll_fd[i].fd); printf("%d vs %dn",poll_fd[i].revents,poll_fd[i].revents); memcpy(poll_fd+i,poll_fd+i+1,poll_fd_cnt-i-1); poll_fd_cnt--; i--;//数组发生变化,重新判断i的fd break; } printf("server recv:%sn",buf); // 报文解析,获取URI int url_start = 0; int url_end = 0; for(int j=0; j<len; j++) { if(buf[j] == ' ') { if(0 == url_start) { url_start = j+1; } else { url_end = j; break; } } } string url(buf+url_start,url_end-url_start); cout << "url:" << url << endl; string file = string(work_dir) + url; cout << "file" << file << endl; char* accept = strstr(buf,"Accept:"); if(NULL == accept) { perror("No Accept"); } char* type = accept + sizeof("Accept:"); int typeLen; for(int j=0; j< len - (type - buf); j++) { if(*(type+j) == ',' || *(type+j) == 'n') { typeLen = j; break; } } int fd = open(file.c_str(),O_RDONLY); if(-1 == fd) { perror("open file err"); // exit(1); } ostringstream oss; oss << "HTTP/1.1 200 OKn"; struct stat file_stat; fstat(fd,&file_stat); oss << "Content-Length:" << file_stat.st_size << endl; oss << "Content-Type:" << string(type,typeLen) << endl << endl; string status = oss.str(); write(poll_fd[i].fd,status.c_str(),status.size()); if(-1 == sendfile(poll_fd[i].fd,fd,NULL,file_stat.st_size)) { perror("sendfile err"); // exit(1); } close(fd); } close(poll_fd[i].fd); } int main(int argc,char* argv[]) { if(4 != argc) { printf("usage:%s <ip> <#port> <dir>n",argv[0]); return 1; } char* work_dir = NULL; work_dir = argv[3]; int listenfd = socket(AF_INET,SOCK_STREAM,0); if(-1 == listenfd) { perror("listenfd open err"); return 1; } printf("socket create OKn"); int flag = 1; setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag)); struct sockaddr_in local_addr; bzero(&local_addr,sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = inet_addr(argv[1]); local_addr.sin_port = htons(atoi(argv[2])); if(-1 == bind(listenfd,(struct sockaddr*)&local_addr,sizeof(local_addr))) { perror("bind err"); return 1; } printf("bind OKn"); if(-1 == listen(listenfd,10)) { perror("listen err"); return 1; } printf("listen OKn"); struct pollfd poll_fd[INR_OPEN_MAX]; poll_fd[0].fd = listenfd; poll_fd[0].events = POLLRDNORM; size_t poll_fd_cnt = 1; for(;;) { if(-1 != poll(poll_fd,poll_fd_cnt,-1)) { if(poll_fd[0].revents == POLLRDNORM) { printf("accept listenfdn"); int connfd = accept(listenfd,NULL,NULL); if(-1 == connfd) { perror("accept err"); } else { if(poll_fd_cnt+1 == INR_OPEN_MAX) { fprintf(stderr,"connfd size over %d",INR_OPEN_MAX); close(connfd); } else { poll_fd[poll_fd_cnt].fd = connfd; poll_fd[poll_fd_cnt].events = POLLRDNORM; poll_fd_cnt++; } } } //初始化线程池 ThreadPool pool(3); int i; for(i=1; i<poll_fd_cnt; i++) { if(poll_fd[i].revents & POLLRDNORM) { //Handle(poll_fd,i,poll_fd_cnt,work_dir); //初始化参数结构体 struct func_t_arg arg; arg.poll_fd = poll_fd; arg.i=i; arg.poll_fd_cnt=poll_fd_cnt; arg.work_dir=work_dir; //往线程池添加任务 pool.AddJob(Handle,arg); } close(listenfd); } } } }
最后
以上就是眯眯眼小刺猬最近收集整理的关于TinyHttp的全部内容,更多相关TinyHttp内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复