\n"
38 | " Options: \n"
39 | " -p, --path path of url \n"
40 | " -P, --port
port of host \n"
41 | " -t, --threads Number of threads to use \n"
42 | " \n"
43 | " -f, --file Load ip file \n"
44 | " -H, --header Add header to request \n"
45 | " --latency Print latency statistics \n"
46 | " --timeout Socket/request timeout \n"
47 | " -v, --version Print version details \n"
48 | " \n"
49 | " Numeric arguments may include a SI unit (1k, 1M, 1G)\n"
50 | " Time arguments may include a time unit (2s, 2m, 2h)\n");
51 | }
52 |
53 | static int parse_args(struct config *cfg, char **headers, int argc, char* argv[])
54 | {
55 | char **header = headers;
56 | int c;
57 | memset(cfg, 0, sizeof(struct config));
58 | cfg->path = "/";
59 | cfg->port = 80;
60 | cfg->file = NULL;
61 | cfg->dynamic = false;
62 | cfg->threads = 1000;
63 |
64 | while ((c = getopt(argc, argv, "f:P:p:t:H:d:h?")) != -1) {
65 | switch (c) {
66 | case 'f':
67 | cfg->file = optarg;
68 | break;
69 | case 'P': cfg->port = atoi(optarg); break;
70 | case 't': cfg->threads = atoi(optarg); break;
71 | case 'p': cfg->path = optarg; break;
72 | case 'H':
73 | *header++ = optarg;
74 | break;
75 | case 'h':
76 | case '?':
77 | default:
78 | return -1;
79 | }
80 | }
81 | *header = NULL;
82 | return 0;
83 | }
84 |
85 | static int create_and_connect( char *host , int *epfd)
86 | {
87 | struct hostent *hp;
88 | struct sockaddr_in addr;
89 |
90 | // epoll mask that contain the list of epoll events attached to a network socket
91 | static struct epoll_event event;
92 |
93 | int sock;
94 | int on = 1;
95 |
96 | if((hp = gethostbyname(host)) == NULL) {
97 | fprintf(stderr,"[NetTools] Invalid server name: %s\n", host);
98 | return -1;
99 | }
100 | bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
101 | addr.sin_port = htons(cfg.port);
102 | addr.sin_family = AF_INET;
103 | sock = socket(AF_INET, SOCK_STREAM, 0);
104 | // set socket to non blocking and allow port reuse
105 | if ( (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int)) ||
106 | fcntl(sock, F_SETFL, O_NONBLOCK)) == -1)
107 | {
108 | perror("setsockopt || fcntl");
109 | exit(1);
110 | }
111 | if( connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1
112 | && errno != EINPROGRESS)
113 | {
114 | // connect doesn't work, are we running out of available ports ? if yes, destruct the socket
115 | if (errno == EAGAIN || errno == EWOULDBLOCK)
116 | {
117 | perror("connect is EAGAIN");
118 | //close(sock);
119 | exit(1);
120 | }
121 | }
122 | else
123 | {
124 | /* epoll will wake up for the following events :
125 | *
126 | * EPOLLIN : The associated file is available for read(2) operations.
127 | *
128 | * EPOLLOUT : The associated file is available for write(2) operations.
129 | *
130 | * EPOLLRDHUP : Stream socket peer closed connection, or shut down writing
131 | * half of connection. (This flag is especially useful for writing simple
132 | * code to detect peer shutdown when using Edge Triggered monitoring.)
133 | *
134 | * EPOLLERR : Error condition happened on the associated file descriptor.
135 | * epoll_wait(2) will always wait for this event; it is not necessary to set it in events.
136 | */
137 | event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR | EPOLLET;
138 | //Edgvent.events = EPOLLOUT | EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET;
139 |
140 | event.data.ptr = malloc(sizeof(event_ptr));
141 |
142 | struct event_ptr *ptr = event.data.ptr;
143 | bzero(ptr, sizeof(event_ptr));
144 | ptr->fd = sock;
145 | ptr->rein = 0;
146 | strcpy(ptr->addr, host);
147 | //ptr->addr[strlen(host)] = '\0';
148 |
149 | // add the socket to the epoll file descriptors
150 | if(epoll_ctl((int)*epfd, EPOLL_CTL_ADD, sock, &event) != 0)
151 | {
152 | perror("epoll_ctl, adding socket\n");
153 | exit(1);
154 | }
155 | }
156 |
157 | return 0;
158 | }
159 |
160 | /* reading waiting errors on the socket
161 | * return 0 if there's no, 1 otherwise
162 | */
163 | int socket_check(int fd)
164 | {
165 | int ret;
166 | int code;
167 | int len = sizeof(int);
168 |
169 | ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &code, &len);
170 |
171 | if ((ret || code)!= 0)
172 | return 1;
173 |
174 | return 0;
175 | }
176 |
177 | void stringlink(char *s, char *t)
178 | {
179 | while (*s != '\0')
180 | {
181 | s++;
182 | }
183 | while (*t != '\0')
184 | {
185 | *s++ = *t++;
186 | }
187 | *s = '\0';
188 | }
189 |
190 | char* substring(const char* str, size_t begin, size_t len)
191 | {
192 | if (str == 0 || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin+len))
193 | return 0;
194 |
195 | return strndup(str + begin, len);
196 | }
197 |
198 | char *substr(char *haystack, char *begin, char *end)
199 | {
200 | char *ret, *r;
201 | char *b = strstr(haystack, begin);
202 | if (b) {
203 | char *e = strstr(b, end);
204 | if(e) {
205 | int offset = e - b;
206 | int retlen = offset - strlen(begin);
207 | if ((ret = malloc(retlen + 1)) == NULL)
208 | return NULL;
209 | strncpy(ret, b + strlen(begin), retlen);
210 | return ret;
211 | }
212 | }
213 | return NULL;
214 | }
215 |
216 | void main(int argc, char* argv[])
217 | {
218 | char *url, **headers;
219 | headers = malloc((argc / 2) * sizeof(char *));
220 |
221 | if (parse_args(&cfg, headers, argc, argv)) {
222 | usage();
223 | exit(1);
224 | }
225 |
226 | char **h;
227 | char header_name[32];
228 | char header_value[200];
229 | char header[1024];
230 | char header_tmp[232];
231 | event_ptr * ptr;
232 |
233 | if (cfg.file) {
234 | FILE *fp;
235 | char buf[MAX_LINE]; /*缓冲区*/
236 | int n, len ;
237 | fp = fopen(cfg.file, "r");
238 | if (fp == NULL) {
239 | printf("file not exist :%s\n", cfg.file);
240 | exit(1);
241 | }
242 | n = 0;
243 | int epfd;
244 | static struct epoll_event *events;
245 |
246 | // create the special epoll file descriptor
247 | epfd = epoll_create(cfg.threads);
248 |
249 | // allocate enough memory to store all the events in the "events" structure
250 | if (NULL == (events = calloc(cfg.threads, sizeof(struct epoll_event))))
251 | {
252 | perror("calloc events");
253 | exit(1);
254 | };
255 | int rn = 0;
256 | master_worker:
257 | while(fgets(buf, MAX_LINE, fp) != NULL) {
258 | len = strlen(buf);
259 | buf[len-1] = '\0'; /* 去掉换行符 */
260 | if(strlen(buf) >= 7 && create_and_connect(buf, &epfd) != 0)
261 | {
262 | fprintf (stderr, "create and connect : %s\n", buf);
263 | }
264 | ++n;
265 | ++rn;
266 | if(rn > cfg.threads) goto epoll_worker;
267 | }
268 | if (rn == 0) exit(0);
269 |
270 |
271 | epoll_worker:
272 |
273 | sprintf(header, "GET %s HTTP/1.1\r\n", cfg.path);
274 | rn = 0;
275 | for (h = headers; *h; h++) {
276 | char *p = strchr(*h, ':');
277 | if (p && p[1] == ' ') {
278 | bzero(header_name, 32);
279 | bzero(header_value, 200);
280 | bzero(header_tmp, 232);
281 | strncpy(header_name, *h, strlen(*h) - strlen(p));
282 | strcpy(header_value, p + 2);
283 | sprintf(header_tmp, "%s: %s\r\n", header_name, header_value);
284 | stringlink(header, header_tmp);
285 | //printf("p=%p(%d), %s => %s\n", p, strlen(p), header_name, header_value);
286 | }
287 | }
288 | stringlink(header, "\r\n");
289 | int header_len = strlen(header);
290 | char *hhh = malloc( header_len * sizeof(char) + 1);
291 | strcpy(hhh, header);
292 |
293 | printf("%s", hhh);
294 |
295 | char buffer[2049];
296 | int buffersize = 2048;
297 | int count, i, datacount;
298 | int http_status;
299 | char *http_servername = NULL;
300 | char *http_title = NULL;
301 | while(1) {
302 | count = epoll_wait(epfd, events, cfg.threads, 500);
303 | if(count == 0) break;
304 | for(i=0;ifd, ptr->addr, events[i].events);
307 | if ((events[i].events & (EPOLLHUP | EPOLLERR)) || strlen(ptr->addr) == 0)
308 | {
309 |
310 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL);
311 |
312 | //fprintf (stderr, "epoll error %d\n", ptr->fd);
313 | continue;
314 | }
315 | if (events[i].events & EPOLLOUT) //socket is ready for writing
316 | {
317 | // verify the socket is connected and doesn't return an error
318 | if(socket_check(ptr->fd) != 0)
319 | {
320 | perror("write socket_check");
321 | continue;
322 | }
323 | else
324 | {
325 |
326 | int total = header_len;
327 | while(1) {
328 | datacount = send(ptr->fd, hhh, header_len, 0);
329 | if(datacount < 0) {
330 | if (errno == EINTR || errno == EAGAIN) {
331 | usleep(1000);
332 | continue;
333 | }
334 | }
335 | if (datacount == total) {
336 | events[i].events = EPOLLIN | EPOLLHUP | EPOLLERR;
337 |
338 | if(epoll_ctl(epfd, EPOLL_CTL_MOD, ptr->fd, events) != 0)
339 | {
340 | perror("epoll_ctl, modify socket");
341 | continue;
342 | }
343 | break;
344 | }
345 | total -= datacount;
346 | hhh += datacount;
347 | }
348 |
349 | }
350 | }
351 |
352 | if (events[i].events & (EPOLLIN )) //socket is ready for reading
353 | {
354 | // verify the socket is connected and doesn't return an error
355 | if(socket_check(ptr->fd) != 0)
356 | {
357 | fprintf (stderr, " [ %s->%d] read socket_check : [%d]%s\n", ptr->addr, ptr->fd, errno, strerror(errno));
358 | //epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL);
359 | continue;
360 |
361 | }
362 | else
363 | {
364 | memset(buffer,0x0,buffersize);
365 |
366 | int n = 0;
367 | while (1) {
368 | datacount = read(ptr->fd, buffer +n , buffersize);
369 | if(datacount == -1) {
370 | ++ptr->rein;
371 | if (ptr->rein > 5) {
372 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL);
373 | break;
374 | }
375 | if (errno == EAGAIN) {
376 | usleep(1000);
377 | continue;
378 | }
379 |
380 |
381 | }else if(datacount == 0) {
382 | break;
383 | }
384 | //printf("%s=%d=%d\n", buffer, n, datacount);
385 |
386 | n += datacount;
387 | }
388 |
389 |
390 | /*
391 | if((datacount = recv(ptr->fd, buffer, buffersize, 0)) < 0 )
392 | {
393 | ++ptr->rein;
394 | fprintf (stderr, "[ %s->%d] recv failed : %s\n", ptr->addr, ptr->fd, strerror(errno));
395 | if(ptr->rein > 5) {
396 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL);
397 | }
398 | continue;
399 | }
400 | */
401 | printf("%s\n", buffer);
402 | char *http_status = substring(buffer, 9, 3);
403 | http_servername = substr(buffer, "Server: ", "\r\n");
404 | http_title = substr(buffer, "", "");
405 | fprintf (stdout, "%s\t%s\t%s\t%s\n", ptr->addr, http_status, http_servername, http_title);
406 | if(http_status != NULL) free(http_status);
407 | if(http_servername != NULL) free(http_servername);
408 | if(http_title != NULL) free(http_title);
409 |
410 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL);
411 | //usleep(10000);
412 | }
413 | }
414 |
415 | }
416 | }
417 | goto master_worker;
418 | }
419 |
420 | //printf("headers: %s\npath: %s\nport: %d\n", *headers, cfg.path, cfg.port);
421 | }
422 |
--------------------------------------------------------------------------------
/t2.c:
--------------------------------------------------------------------------------
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 |
14 | #define MAX_LINE 1024
15 | #ifndef EPOLLRDHUP
16 | #define EPOLLRDHUP 0x2000
17 | #endif
18 |
19 | #ifdef DEBUG
20 |
21 | void *
22 | debug_malloc(size_t size, const char *file, int line, const char *func)
23 | {
24 | void *p;
25 |
26 | p = malloc(size);
27 | printf("%s:%d:%s:malloc(%ld): p=0x%lx\n",
28 | file, line, func, size, (unsigned long)p);
29 | return p;
30 | }
31 |
32 | #define malloc(s) debug_malloc(s, __FILE__, __LINE__, __func__)
33 | #define free(p) do { \
34 | printf("%s:%d:%s:free(0x%lx)\n", __FILE__, __LINE__, \
35 | __func__, (unsigned long)p); \
36 | free(p); \
37 | } while (0)
38 |
39 | #endif
40 | static struct config {
41 | char *body;
42 | char *file;
43 | char *servername;
44 | char *title;
45 | int port;
46 | int threads;
47 | bool dynamic;
48 | } cfg;
49 |
50 | typedef struct se_ptr_s se_ptr_t;
51 | typedef int (*se_rw_proc_t)(se_ptr_t *ptr);
52 |
53 | struct se_ptr_s {
54 | int loop_fd;
55 | int fd;
56 | se_rw_proc_t rfunc;
57 | se_rw_proc_t wfunc;
58 | char addr[16];
59 | };
60 |
61 | static struct epoll_event events[4096], ev;
62 |
63 |
64 | static void usage() {
65 | printf("Usage: httpv \n"
66 | " Options: \n"
67 | " -b, --body data for socket, default <'GET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n'> \n"
68 | " -P, --port port of host \n"
69 | " -t, --threads Number of threads to use \n"
70 | " -f, --file Load ip file \n"
71 | " -0, --title match title \n"
72 | " -1, --servername match server \n"
73 | " \n");
74 | }
75 | static int parse_args(struct config *cfg, int argc, char* argv[])
76 | {
77 | int c;
78 | memset(cfg, 0, sizeof(struct config));
79 | cfg->body = "GET / HTTP/1.1\r\nAccept-Encoding: deflate\r\nHost: www.baidu.com\r\n\r\n";
80 | cfg->port = 80;
81 | cfg->file = NULL;
82 | cfg->dynamic = false;
83 | cfg->threads = 1000;
84 | cfg->servername = NULL;
85 | cfg->title = NULL;
86 |
87 | while ((c = getopt(argc, argv, "0:1:f:P:b:t:d:h?")) != -1) {
88 | switch (c) {
89 | case 'f':
90 | cfg->file = optarg;
91 | break;
92 | case 'P': cfg->port = atoi(optarg); break;
93 | case 't': cfg->threads = atoi(optarg); break;
94 | case 'b': cfg->body = optarg; break;
95 | case '0': cfg->title = optarg; break;
96 | case '1': cfg->servername = optarg; break;
97 | case 'h':
98 | case '?':
99 | default:
100 | return -1;
101 | }
102 | }
103 | return 0;
104 | }
105 |
106 | char* substring(const char* str, size_t begin, size_t len)
107 | {
108 | if (str == 0 || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin+len))
109 | return 0;
110 |
111 | return strndup(str + begin, len);
112 | }
113 |
114 | char *substr(char *haystack, char *begin, char *end)
115 | {
116 | char *ret, *r;
117 | char *b = strstr(haystack, begin);
118 | if (b) {
119 | char *e = strstr(b, end);
120 | if(e) {
121 | int offset = e - b;
122 | int retlen = offset - strlen(begin);
123 | if ((ret = malloc(retlen + 1)) == NULL)
124 | return NULL;
125 | ret[retlen] = '\0';
126 | strncpy(ret, b + strlen(begin), retlen);
127 | return ret;
128 | }
129 | }
130 | return NULL;
131 | }
132 |
133 | bool setnonblocking(int sockfd) {
134 | int opts;
135 |
136 | opts = fcntl(sockfd, F_GETFL);
137 | if(opts < 0) {
138 | perror("fcntl(F_GETFL)\n");
139 | return false;
140 | }
141 | opts = (opts | O_NONBLOCK);
142 | if(fcntl(sockfd, F_SETFL, opts) < 0) {
143 | perror("fcntl(F_SETFL)\n");
144 | return false;
145 | }
146 | return true;
147 | }
148 |
149 | static int connected( char *host)
150 | {
151 | struct hostent *hp;
152 | struct sockaddr_in addr;
153 |
154 | // epoll mask that contain the list of epoll events attached to a network socket
155 | static struct epoll_event event;
156 |
157 | int sock;
158 | int on = 1;
159 |
160 | if((hp = gethostbyname(host)) == NULL) {
161 | fprintf(stderr,"[NetTools] Invalid server name: %s\n", host);
162 | return -1;
163 | }
164 | memset(&addr, 0, sizeof (addr));
165 | bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
166 | addr.sin_port = htons(cfg.port);
167 | addr.sin_family = AF_INET;
168 | sock = socket(AF_INET, SOCK_STREAM, 0);
169 | if (sock < 0)
170 | {
171 | fprintf(stderr, "create socket fail");
172 | return -5;
173 | }
174 | // set socket to non blocking and allow port reuse
175 | if ( (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int)) ||
176 | !setnonblocking(sock)))
177 | {
178 | fprintf(stderr, "setsockopt || fcntl");
179 | return -2;
180 | }
181 | int res = connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
182 |
183 | if (res < 0) {
184 | if (errno == EINPROGRESS) {
185 | return sock;
186 | }
187 | close(sock);
188 | return -3;
189 | }
190 | return sock;
191 | }
192 |
193 | int socket_check(int fd)
194 | {
195 | int ret;
196 | int code;
197 | int len = sizeof(int);
198 |
199 | ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &code, &len);
200 |
201 | if ((ret || code)!= 0)
202 | return 1;
203 |
204 | return 0;
205 | }
206 | int se_create(int event_size)
207 | {
208 | return epoll_create(event_size);
209 | }
210 |
211 | se_ptr_t *se_add(int loop_fd, int fd)
212 | {
213 | se_ptr_t *ptr = malloc(sizeof(se_ptr_t));
214 |
215 | if(!ptr) {
216 | return ptr;
217 | }
218 |
219 | ptr->loop_fd = loop_fd;
220 | ptr->fd = fd;
221 |
222 | ev.data.ptr = ptr;
223 | ev.events = EPOLLPRI;
224 |
225 | int ret = epoll_ctl(loop_fd, EPOLL_CTL_ADD, fd, &ev);
226 |
227 | if(ret < 0) {
228 | free(ptr);
229 | ptr = NULL;
230 | }
231 | return ptr;
232 | }
233 |
234 | int se_delete(se_ptr_t *ptr)
235 | {
236 | if(!ptr) {
237 | return -1;
238 | }
239 |
240 | if(epoll_ctl(ptr->loop_fd, EPOLL_CTL_DEL, ptr->fd, &ev) < 0) {
241 | return -1;
242 | }
243 |
244 | free(ptr);
245 |
246 | return 0;
247 | }
248 |
249 | int se_loop(int loop_fd, int waitout)
250 | {
251 | int n = 0, i = 0;
252 | se_ptr_t *ptr = NULL;
253 |
254 | while(1) {
255 |
256 | n = epoll_wait(loop_fd, events, 4096, waitout);
257 | if(n == 0) break;
258 | for(i = 0; i < n; i++) {
259 | ptr = events[i].data.ptr;
260 |
261 | if (events[i].events & ( EPOLLHUP | EPOLLERR))
262 | {
263 | se_delete(ptr);
264 | } else if(events[i].events & (EPOLLIN) && ptr->rfunc) {
265 | //printf("rfunc\n");
266 | ptr->rfunc(ptr);
267 |
268 | } else if(events[i].events & (EPOLLOUT) && ptr->wfunc) {
269 | //printf("wfunc\n");
270 | ptr->wfunc(ptr);
271 | }
272 | }
273 |
274 | if(n == -1 && errno != EINTR) {
275 | printf("exit\n");
276 | break;
277 | }
278 | }
279 |
280 | return 0;
281 | }
282 |
283 | int se_be_read(se_ptr_t *ptr, se_rw_proc_t func)
284 | {
285 | ptr->rfunc = func;
286 | ptr->wfunc = NULL;
287 |
288 | ev.data.ptr = ptr;
289 | ev.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLONESHOT;
290 |
291 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev);
292 | }
293 |
294 | int se_be_write(se_ptr_t *ptr, se_rw_proc_t func)
295 | {
296 | ptr->rfunc = NULL;
297 | ptr->wfunc = func;
298 |
299 | ev.data.ptr = ptr;
300 | ev.events = EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLET;
301 |
302 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev);
303 | }
304 |
305 | int se_be_pri(se_ptr_t *ptr, se_rw_proc_t func)
306 | {
307 | ptr->rfunc = func;
308 | ptr->wfunc = NULL;
309 |
310 | ev.data.ptr = ptr;
311 | ev.events = EPOLLPRI;
312 |
313 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev);
314 | }
315 |
316 | int se_be_rw(se_ptr_t *ptr, se_rw_proc_t rfunc, se_rw_proc_t wfunc)
317 | {
318 | ptr->rfunc = rfunc;
319 | ptr->wfunc = wfunc;
320 |
321 | ev.data.ptr = ptr;
322 | ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLERR;
323 |
324 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev);
325 | }
326 |
327 | int network_be_read(se_ptr_t *ptr)
328 | {
329 | char *response = NULL;
330 | char buffer[1500];
331 | int read_size , total_size = 0;
332 | if (socket_check(ptr->fd) == 1)
333 | {
334 | fprintf (stderr, " [ %s->%d] read socket_check : [%d]%s\n", ptr->addr, ptr->fd, errno, strerror(errno));
335 | //se_be_read(ptr, network_be_read);
336 | return 1;
337 | }
338 | bzero(buffer, 1500);
339 | while( (read_size = recv(ptr->fd , buffer , sizeof(buffer) , 0) ))
340 | {
341 | if((errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)) {
342 | fprintf (stderr, " recv[%d] : [%d]%s\n",read_size, errno, strerror(errno));
343 | continue;
344 | }
345 | response = realloc(response , read_size + total_size);
346 | if(response == NULL)
347 | {
348 | printf("realloc failed");
349 | exit(1);
350 | }
351 | memcpy((response + total_size) , buffer , read_size);
352 | total_size += read_size;
353 | }
354 | response = realloc(response , total_size + 1);
355 | *(response + total_size) = '\0';
356 | if(total_size > 0) {
357 | int m0 = 0;
358 | int m1 = 0;
359 | //printf("read %d=%d: %s\n", n, nread, buffer);
360 | char *http_status = substring(buffer, 9, 3);
361 | char *http_servername = substr(buffer, "Server: ", "\r\n");
362 | char *http_title = substr(buffer, "", "");
363 | if (cfg.title != NULL) {
364 | ++m0;
365 | if (http_title != NULL && strstr(http_title, cfg.title) != NULL)++m1;
366 | }
367 | if (cfg.servername != NULL) {
368 | ++m0;
369 | if (http_servername != NULL && strstr(http_servername, cfg.servername) != NULL)++m1;
370 | }
371 |
372 | if( m0 == m1)fprintf(stdout, "%s\t%s\t%s\t%s\n", ptr->addr, http_status, http_servername, http_title);
373 | if(http_status != NULL) free(http_status);
374 | if(http_servername != NULL) free(http_servername);
375 | if(http_title != NULL) free(http_title);
376 | }
377 | if(response != NULL) free(response);
378 | close(ptr->fd);
379 | se_delete(ptr);
380 | return total_size;
381 |
382 | }
383 | int network_be_write(se_ptr_t *ptr)
384 | {
385 | int rs;
386 |
387 | if (socket_check(ptr->fd) == 1)
388 | {
389 | fprintf (stderr, " [ %s->%d] write socket_check : [%d]%s\n", ptr->addr, ptr->fd, errno, strerror(errno));
390 | se_delete(ptr);
391 | //se_be_write(ptr, network_be_write);
392 | return 1;
393 | }
394 | rs = send(ptr->fd, cfg.body, strlen(cfg.body), 0);
395 | if (rs < 0) {
396 | printf("send error [%d]%s\n", errno, strerror(errno));
397 | se_delete(ptr);
398 | return 1;
399 | }
400 | se_be_read(ptr, network_be_read);
401 |
402 | }
403 | void main(int argc, char* argv[])
404 | {
405 | int epfd;
406 | signal(SIGPIPE, SIG_IGN); //oops strace
407 | if (parse_args(&cfg, argc, argv)) {
408 | usage();
409 | exit(1);
410 | }
411 | if (cfg.file) {
412 | FILE *fp;
413 | char buf[MAX_LINE];
414 | int n, len ;
415 | fp = fopen(cfg.file, "r");
416 | if (fp == NULL) {
417 | printf("file not exist :%s\n", cfg.file);
418 | exit(1);
419 | }
420 | n = 0;
421 | epfd = se_create(1024);
422 | int rn = 0;
423 | master_worker:
424 | while(fgets(buf, MAX_LINE, fp) != NULL) {
425 | len = strlen(buf);
426 | buf[len-1] = '\0';
427 | if(strlen(buf) >= 7)
428 | {
429 | int sockfd = connected(buf);
430 | if (sockfd > 0)
431 | {
432 | se_ptr_t *ptr = se_add(epfd, sockfd);
433 | strcpy(ptr->addr, buf);
434 | se_be_write(ptr, network_be_write);
435 | }
436 | //fprintf (stderr, "create and connect : %s=%d\n", buf, sockfd);
437 | }
438 | ++n;
439 | ++rn;
440 | if(rn > cfg.threads) goto epoll_worker;
441 | }
442 | if (rn == 0) exit(0);
443 | epoll_worker:
444 | fprintf (stderr, "work line: %d - %d\n", (n-cfg.threads) < 0 ? 1 : (n-cfg.threads), n);
445 | rn = 0;
446 | se_loop(epfd, 4000);
447 | goto master_worker;
448 | }
449 | fprintf (stderr, "work done\n");
450 | }
451 |
--------------------------------------------------------------------------------