client.c
来自「-」· C语言 代码 · 共 399 行
C
399 行
/* * $Id: client.c,v 1.81.2.1 1999/02/14 08:35:00 wessels Exp $ * * DEBUG: section 0 WWW Client * AUTHOR: Harvest Derived * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"#ifndef BUFSIZ#define BUFSIZ 8192#endif/* Local functions */static int client_comm_connect(int, char *, u_short, struct timeval *);static void usage(const char *progname);static int Now(struct timeval *);static SIGHDLR catch;static SIGHDLR pipe_handler;static void set_our_signal();static int put_fd;static char *put_file = NULL;static struct stat sb;int total_bytes = 0;static voidusage(const char *progname){ fprintf(stderr, "Usage: %s [-arsv] [-i IMS] [-h host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] url\n" "Options:\n" " -P file PUT request.\n" " -a Do NOT include Accept: header.\n" " -r Force cache to reload URL.\n" " -s Silent. Do not print data to stdout.\n" " -v Verbose. Print outgoing message to stderr.\n" " -i IMS If-Modified-Since time (in Epoch seconds).\n" " -h host Retrieve URL from cache on hostname. Default is localhost.\n" " -p port Port number of cache. Default is %d.\n" " -m method Request method, default is GET.\n" " -t count Trace count cache-hops\n" " -g count Ping mode, \"count\" iterations (0 to loop until interrupted).\n" " -I interval Ping interval in seconds (default 1 second).\n" " -H 'string' Extra headers to send. Use '\\n' for new lines.\n", progname, CACHE_HTTP_PORT); exit(1);}static int interrupted = 0;intmain(int argc, char *argv[]){ int conn, c, len, bytesWritten; int port, to_stdout, reload; int ping, pcount; int keep_alive = 0; int opt_noaccept = 0; int opt_put = 0; int opt_verbose = 0; char url[BUFSIZ], msg[BUFSIZ], buf[BUFSIZ], hostname[BUFSIZ]; char extra_hdrs[BUFSIZ]; const char *method = "GET"; extern char *optarg; time_t ims = 0; int max_forwards = -1; struct timeval tv1, tv2; int i = 0, loops; long ping_int; long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0; /* set the defaults */ strcpy(hostname, "localhost"); extra_hdrs[0] = '\0'; port = CACHE_HTTP_PORT; to_stdout = 1; reload = 0; ping = 0; pcount = 0; ping_int = 1 * 1000; if (argc < 2) { usage(argv[0]); /* need URL */ } else if (argc >= 2) { strcpy(url, argv[argc - 1]); if (url[0] == '-') usage(argv[0]); while ((c = getopt(argc, argv, "ah:P:i:km:p:rsvt:g:p:I:H:?")) != -1) switch (c) { case 'a': opt_noaccept = 1; break; case 'h': /* host:arg */ if (optarg != NULL) strcpy(hostname, optarg); break; case 's': /* silent */ to_stdout = 0; break; case 'k': /* backward compat */ keep_alive = 1; break; case 'r': /* reload */ reload = 1; break; case 'p': /* port number */ sscanf(optarg, "%d", &port); if (port < 1) port = CACHE_HTTP_PORT; /* default */ break; case 'P': put_file = xstrdup(optarg); break; case 'i': /* IMS */ ims = (time_t) atoi(optarg); break; case 'm': method = xstrdup(optarg); break; case 't': method = xstrdup("TRACE"); max_forwards = atoi(optarg); break; case 'g': ping = 1; pcount = atoi(optarg); to_stdout = 0; break; case 'I': if ((ping_int = atoi(optarg) * 1000) <= 0) usage(argv[0]); break; case 'H': if (strlen(optarg)) { char *t; strncpy(extra_hdrs, optarg, sizeof(extra_hdrs)); while ((t = strstr(extra_hdrs, "\\n"))) *t = '\r', *(t + 1) = '\n'; } break; case 'v': /* undocumented: may increase verb-level by giving more -v's */ opt_verbose++; break; case '?': /* usage */ default: usage(argv[0]); break; } } /* Build the HTTP request */ if (strncmp(url, "mgr:", 4) == 0) { char *t = xstrdup(url + 4); snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t); xfree(t); } if (put_file) { opt_put = 1; /*method = xstrdup("PUT"); */ put_fd = open(put_file, O_RDONLY); set_our_signal(); if (put_fd < 0) { fprintf(stderr, "%s: can't open file (%s)\n", argv[0], xstrerror()); exit(-1); } fstat(put_fd, &sb); } snprintf(msg, BUFSIZ, "%s %s HTTP/1.0\r\n", method, url); if (reload) { snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n"); strcat(msg, buf); } if (put_fd > 0) { snprintf(buf, BUFSIZ, "Content-length: %d\r\n", (int) sb.st_size); strcat(msg, buf); } if (opt_noaccept == 0) { snprintf(buf, BUFSIZ, "Accept: */*\r\n"); strcat(msg, buf); } if (ims) { snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims)); strcat(msg, buf); } if (max_forwards > -1) { snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards); strcat(msg, buf); } if (keep_alive) { if (port != 80) snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n"); else snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n"); strcat(msg, buf); } strcat(msg, extra_hdrs); snprintf(buf, BUFSIZ, "\r\n"); strcat(msg, buf); if (opt_verbose) fprintf(stderr, "headers: '%s'\n", msg); if (ping) {#if HAVE_SIGACTION struct sigaction sa, osa; if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { sa.sa_handler = catch; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); (void) sigaction(SIGINT, &sa, NULL); }#else void (*osig) (); if ((osig = signal(SIGINT, catch)) != SIG_DFL) (void) signal(SIGINT, osig);#endif } loops = ping ? pcount : 1; for (i = 0; loops == 0 || i < loops; i++) { /* Connect to the server */ if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("client: socket"); exit(1); } if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) { if (errno == 0) { fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port); } else { char tbuf[BUFSIZ]; snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d", hostname, port); perror(tbuf); } exit(1); } /* Send the HTTP request */ bytesWritten = write(conn, msg, strlen(msg)); if (bytesWritten < 0) { perror("client: ERROR: write"); exit(1); } else if (bytesWritten != strlen(msg)) { fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); exit(1); } if (put_file) { int x; lseek(put_fd, 0, SEEK_SET); while ((x = read(put_fd, buf, sizeof(buf))) > 0) { x = write(conn, buf, x); total_bytes += x; if (x <= 0) break; } if (x != 0) fprintf(stderr, "client: ERROR: Cannot send file.\n"); } /* Read the data */ while ((len = read(conn, buf, sizeof(buf))) > 0) { if (to_stdout) fwrite(buf, len, 1, stdout); } (void) close(conn); /* done with socket */ if (interrupted) break; if (ping) { struct tm *tmp; time_t t2s; long elapsed_msec; (void) Now(&tv2); elapsed_msec = tvSubMsec(tv1, tv2); t2s = tv2.tv_sec; tmp = localtime(&t2s); fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs\n", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1, elapsed_msec / 1000, elapsed_msec % 1000); if (i == 0 || elapsed_msec < ping_min) ping_min = elapsed_msec; if (i == 0 || elapsed_msec > ping_max) ping_max = elapsed_msec; ping_sum += elapsed_msec; /* Delay until next "ping_int" boundary */ if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) { struct timeval tvs; long msec_left = ping_int - elapsed_msec; tvs.tv_sec = msec_left / 1000; tvs.tv_usec = (msec_left % 1000) * 1000; select(0, NULL, NULL, NULL, &tvs); } } } if (ping && i) { ping_mean = ping_sum / i; fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = " "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i, ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000, ping_max / 1000, ping_max % 1000); } exit(0); /*NOTREACHED */ return 0;}static intclient_comm_connect(int sock, char *dest_host, u_short dest_port, struct timeval *tvp){ static const struct hostent *hp = NULL; static struct sockaddr_in to_addr; /* Set up the destination socket address for message to send to. */ if (hp == NULL) { to_addr.sin_family = AF_INET; if ((hp = gethostbyname(dest_host)) == 0) { return (-1); } xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length); to_addr.sin_port = htons(dest_port); } if (tvp) (void) Now(tvp); return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in));}static intNow(struct timeval *tp){#if GETTIMEOFDAY_NO_TZP return gettimeofday(tp);#else return gettimeofday(tp, NULL);#endif} /* ARGSUSED */static voidcatch(int sig){ interrupted = 1; fprintf(stderr, "Interrupted.\n");}static voidpipe_handler(int sig){ fprintf(stderr, "SIGPIPE received.\n");}static voidset_our_signal(){#if HAVE_SIGACTION struct sigaction sa; sa.sa_handler = pipe_handler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); if (sigaction(SIGPIPE, &sa, NULL) < 0) { fprintf(stderr, "Cannot set PIPE signal.\n"); exit(-1); }#else signal(SIGPIPE, pipe_handler);#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?