当前位置: 首页> 房产> 家装 > 网站模板怎么打开_江苏市场监督管理局app_seo排名如何_教育培训机构

网站模板怎么打开_江苏市场监督管理局app_seo排名如何_教育培训机构

时间:2025/7/12 10:41:07来源:https://blog.csdn.net/weixin_43466192/article/details/142988634 浏览次数:0次
网站模板怎么打开_江苏市场监督管理局app_seo排名如何_教育培训机构
/** Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.* All Rights Reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met: ** 1. Redistributions of source code must retain the above copyright*    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright*    notice, this list of conditions and the following disclaimer in the*    documentation and/or other materials provided with the distribution.* 3. Neither the name of Silicon Graphics, Inc. nor the names of its*    contributors may be used to endorse or promote products derived from*    this software without specific prior written permission. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT* HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/系统socket编成,listen后在accept阻塞监听:[连接](https://blog.csdn.net/qq_36784975/article/details/88768320?ops_request_misc=%257B%2522request%255Fid%2522%253A%25220BE0E468-2E50-442E-B409-280726303185%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=0BE0E468-2E50-442E-B409-280726303185&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-88768320-null-null.142%5Ev100%5Epc_search_result_base4&utm_term=socket%28PF_INET,%20SOCK_STREAM,%200%29%29&spm=1018.2226.3001.4187)源码:[连接](https://download.csdn.net/download/weixin_43466192/89891912)
罗老师:[https://blog.csdn.net/u012117034/article/details/135124626](https://blog.csdn.net/u012117034/article/details/135124626)
源码目录介绍:[https://blog.csdn.net/caoshangpa/article/details/79582873](https://blog.csdn.net/caoshangpa/article/details/79582873)#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <pwd.h>
#include "st.h"/******************************************************************* Server configuration parameters*//* Log files */
#define PID_FILE    "pid"
#define ERRORS_FILE "errors"
#define ACCESS_FILE "access"/* Default server port */
#define SERV_PORT_DEFAULT 8000/* Socket listen queue size */
#define LISTENQ_SIZE_DEFAULT 256/* Max number of listening sockets ("hardware virtual servers") */
#define MAX_BIND_ADDRS 16/* Max number of "spare" threads per process per socket */
#define MAX_WAIT_THREADS_DEFAULT 8/* Number of file descriptors needed to handle one client session */
#define FD_PER_THREAD 2/* Access log buffer flushing interval (in seconds) */
#define ACCLOG_FLUSH_INTERVAL 30/* Request read timeout (in seconds) */
#define REQUEST_TIMEOUT 30/******************************************************************* Global data*/struct socket_info {st_netfd_t nfd;               /* Listening socket                     */char *addr;                   /* Bind address                         */unsigned int port;            /* Port                                 */int wait_threads;             /* Number of threads waiting to accept  */int busy_threads;             /* Number of threads processing request */int rqst_count;               /* Total number of processed requests   */
} srv_socket[MAX_BIND_ADDRS];   /* Array of listening sockets           */static int sk_count = 0;        /* Number of listening sockets          */static int vp_count = 0;        /* Number of server processes (VPs)     */
static pid_t *vp_pids;          /* Array of VP pids                     */static int my_index = -1;       /* Current process index */
static pid_t my_pid = -1;       /* Current process pid   */static st_netfd_t sig_pipe[2];  /* Signal pipe           *//** Configuration flags/parameters*/
static int interactive_mode = 0;
static int serialize_accept = 0;
static int log_access       = 0;
static char *logdir     = NULL;
static char *username   = NULL;
static int listenq_size = LISTENQ_SIZE_DEFAULT;
static int errfd        = STDERR_FILENO;/** Thread throttling parameters (all numbers are per listening socket).* Zero values mean use default.*/
static int max_threads = 0;       /* Max number of threads         */
static int max_wait_threads = 0;  /* Max number of "spare" threads */
static int min_wait_threads = 2;  /* Min number of "spare" threads *//******************************************************************* Useful macros*/#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif#define SEC2USEC(s) ((s)*1000000LL)#define WAIT_THREADS(i)  (srv_socket[i].wait_threads)
#define BUSY_THREADS(i)  (srv_socket[i].busy_threads)
#define TOTAL_THREADS(i) (WAIT_THREADS(i) + BUSY_THREADS(i))
#define RQST_COUNT(i)    (srv_socket[i].rqst_count)/******************************************************************* Forward declarations*/static void usage(const char *progname);
static void parse_arguments(int argc, char *argv[]);
static void start_daemon(void);
static void set_thread_throttling(void);
static void create_listeners(void);
static void change_user(void);
static void open_log_files(void);
static void start_processes(void);
static void wdog_sighandler(int signo);
static void child_sighandler(int signo);
static void install_sighandlers(void);
static void start_threads(void);
static void *process_signals(void *arg);
static void *flush_acclog_buffer(void *arg);
static void *handle_connections(void *arg);
static void dump_server_info(void);static void Signal(int sig, void (*handler)(int));
static int cpu_count(void);extern void handle_session(long srv_socket_index, st_netfd_t cli_nfd);
extern void load_configs(void);
extern void logbuf_open(void);
extern void logbuf_flush(void);
extern void logbuf_close(void);/* Error reporting functions defined in the error.c file */
extern void err_sys_report(int fd, const char *fmt, ...);
extern void err_sys_quit(int fd, const char *fmt, ...);
extern void err_sys_dump(int fd, const char *fmt, ...);
extern void err_report(int fd, const char *fmt, ...);
extern void err_quit(int fd, const char *fmt, ...);/** General server example: accept a client connection and do something.* This program just outputs a short HTML page, but can be easily adapted* to do other things.** This server creates a constant number of processes ("virtual processors"* or VPs) and replaces them when they die. Each virtual processor manages* its own independent set of state threads (STs), the number of which varies* with load against the server. Each state thread listens to exactly one* listening socket. The initial process becomes the watchdog, waiting for* children (VPs) to die or for a signal requesting termination or restart.* Upon receiving a restart signal (SIGHUP), all VPs close and then reopen* log files and reload configuration. All currently active connections remain* active. It is assumed that new configuration affects only request* processing and not the general server parameters such as number of VPs,* thread limits, bind addresses, etc. Those are specified as command line* arguments, so the server has to be stopped and then started again in order* to change them.** Each state thread loops processing connections from a single listening* socket. Only one ST runs on a VP at a time, and VPs do not share memory,* so no mutual exclusion locking is necessary on any data, and the entire* server is free to use all the static variables and non-reentrant library* functions it wants, greatly simplifying programming and debugging and* increasing performance (for example, it is safe to ++ and -- all global* counters or call inet_ntoa(3) without any mutexes). The current thread on* each VP maintains equilibrium on that VP, starting a new thread or* terminating itself if the number of spare threads exceeds the lower or* upper limit.** All I/O operations on sockets must use the State Thread library's I/O* functions because only those functions prevent blocking of the entire VP* process and perform state thread scheduling.*/
int main(int argc, char *argv[])
{/* Parse command-line options */parse_arguments(argc, argv);/* Allocate array of server pids */if ((vp_pids = calloc(vp_count, sizeof(pid_t))) == NULL)err_sys_quit(errfd, "ERROR: calloc failed");/* Start the daemon */if (!interactive_mode)start_daemon();/* Initialize the ST library */if (st_init() < 0)err_sys_quit(errfd, "ERROR: initialization failed: st_init");/* Set thread throttling parameters */set_thread_throttling();/* Create listening sockets */create_listeners();/* Change the user */if (username)change_user();/* Open log files */open_log_files();/* Start server processes (VPs) */start_processes();/* Turn time caching on */st_timecache_set(1);/* Install signal handlers */install_sighandlers();/* Load configuration from config files */load_configs();/* Start all threads */start_threads();/* Become a signal processing thread */process_signals(NULL);/* NOTREACHED */return 1;
}/******************************************************************/static void usage(const char *progname)
{fprintf(stderr, "Usage: %s -l <log_directory> [<options>]\n\n""Possible options:\n\n""\t-b <host>:<port>        Bind to specified address. Multiple"" addresses\n""\t                        are permitted.\n""\t-p <num_processes>      Create specified number of processes.\n""\t-t <min_thr>:<max_thr>  Specify thread limits per listening"" socket\n""\t                        across all processes.\n""\t-u <user>               Change server's user id to specified"" value.\n""\t-q <backlog>            Set max length of pending connections"" queue.\n""\t-a                      Enable access logging.\n""\t-i                      Run in interactive mode.\n""\t-S                      Serialize all accept() calls.\n""\t-h                      Print this message.\n",progname);exit(1);
}/******************************************************************/static void parse_arguments(int argc, char *argv[])
{extern char *optarg;int opt;char *c;while ((opt = getopt(argc, argv, "b:p:l:t:u:q:aiSh")) != EOF) {switch (opt) {case 'b':if (sk_count >= MAX_BIND_ADDRS)err_quit(errfd, "ERROR: max number of bind addresses (%d) exceeded",MAX_BIND_ADDRS);if ((c = strdup(optarg)) == NULL)err_sys_quit(errfd, "ERROR: strdup");srv_socket[sk_count++].addr = c;break;case 'p':vp_count = atoi(optarg);if (vp_count < 1)err_quit(errfd, "ERROR: invalid number of processes: %s", optarg);break;case 'l':logdir = optarg;break;case 't':max_wait_threads = (int) strtol(optarg, &c, 10);if (*c++ == ':')max_threads = atoi(c);if (max_wait_threads < 0 || max_threads < 0)err_quit(errfd, "ERROR: invalid number of threads: %s", optarg);break;case 'u':username = optarg;break;case 'q':listenq_size = atoi(optarg);if (listenq_size < 1)err_quit(errfd, "ERROR: invalid listen queue size: %s", optarg);break;case 'a':log_access = 1;break;case 'i':interactive_mode = 1;break;case 'S':/** Serialization decision is tricky on some platforms. For example,* Solaris 2.6 and above has kernel sockets implementation, so supposedly* there is no need for serialization. The ST library may be compiled* on one OS version, but used on another, so the need for serialization* should be determined at run time by the application. Since it's just* an example, the serialization decision is left up to user.* Only on platforms where the serialization is never needed on any OS* version st_netfd_serialize_accept() is a no-op.*/serialize_accept = 1;break;case 'h':case '?':usage(argv[0]);}}if (logdir == NULL && !interactive_mode) {err_report(errfd, "ERROR: logging directory is required\n");usage(argv[0]);}if (getuid() == 0 && username == NULL)err_report(errfd, "WARNING: running as super-user!");if (vp_count == 0 && (vp_count = cpu_count()) < 1)vp_count = 1;if (sk_count == 0) {sk_count = 1;srv_socket[0].addr = "0.0.0.0";}
}/******************************************************************/static void start_daemon(void)
{pid_t pid;/* Start forking */if ((pid = fork()) < 0)err_sys_quit(errfd, "ERROR: fork");if (pid > 0)exit(0);                  /* parent *//* First child process */setsid();                   /* become session leader */if ((pid = fork()) < 0)err_sys_quit(errfd, "ERROR: fork");if (pid > 0)                /* first child */exit(0);umask(022);if (chdir(logdir) < 0)err_sys_quit(errfd, "ERROR: can't change directory to %s: chdir", logdir);
}/******************************************************************* For simplicity, the minimal size of thread pool is considered* as a maximum number of spare threads (max_wait_threads) that* will be created upon server startup. The pool size can grow up* to the max_threads value. Note that this is a per listening* socket limit. It is also possible to limit the total number of* threads for all sockets rather than impose a per socket limit.*/static void set_thread_throttling(void)
{/** Calculate total values across all processes.* All numbers are per listening socket.*/if (max_wait_threads == 0)max_wait_threads = MAX_WAIT_THREADS_DEFAULT * vp_count;/* Assuming that each client session needs FD_PER_THREAD file descriptors */if (max_threads == 0)max_threads = (st_getfdlimit() * vp_count) / FD_PER_THREAD / sk_count;if (max_wait_threads > max_threads)max_wait_threads = max_threads;/** Now calculate per-process values.*/if (max_wait_threads % vp_count)max_wait_threads = max_wait_threads / vp_count + 1;elsemax_wait_threads = max_wait_threads / vp_count;if (max_threads % vp_count)max_threads = max_threads / vp_count + 1;elsemax_threads = max_threads / vp_count;if (min_wait_threads > max_wait_threads)min_wait_threads = max_wait_threads;
}/******************************************************************/static void create_listeners(void)
{int i, n, sock;char *c;struct sockaddr_in serv_addr;struct hostent *hp;unsigned short port;for (i = 0; i < sk_count; i++) {port = 0;if ((c = strchr(srv_socket[i].addr, ':')) != NULL) {*c++ = '\0';port = (unsigned short) atoi(c);}if (srv_socket[i].addr[0] == '\0')srv_socket[i].addr = "0.0.0.0";if (port == 0)port = SERV_PORT_DEFAULT;/* Create server socket */if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)err_sys_quit(errfd, "ERROR: can't create socket: socket");n = 1;if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n)) < 0)err_sys_quit(errfd, "ERROR: can't set SO_REUSEADDR: setsockopt");memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(port);serv_addr.sin_addr.s_addr = inet_addr(srv_socket[i].addr);if (serv_addr.sin_addr.s_addr == INADDR_NONE) {/* not dotted-decimal */if ((hp = gethostbyname(srv_socket[i].addr)) == NULL)err_quit(errfd, "ERROR: can't resolve address: %s",srv_socket[i].addr);memcpy(&serv_addr.sin_addr, hp->h_addr, hp->h_length);}srv_socket[i].port = port;/* Do bind and listen */if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)err_sys_quit(errfd, "ERROR: can't bind to address %s, port %hu",srv_socket[i].addr, port);if (listen(sock, listenq_size) < 0)err_sys_quit(errfd, "ERROR: listen");/* Create file descriptor object from OS socket */if ((srv_socket[i].nfd = st_netfd_open_socket(sock)) == NULL)err_sys_quit(errfd, "ERROR: st_netfd_open_socket");/** On some platforms (e.g. IRIX, Linux) accept() serialization is never* needed for any OS version.  In that case st_netfd_serialize_accept()* is just a no-op. Also see the comment above.*/if (serialize_accept && st_netfd_serialize_accept(srv_socket[i].nfd) < 0)err_sys_quit(errfd, "ERROR: st_netfd_serialize_accept");}
}/******************************************************************/static void change_user(void)
{struct passwd *pw;if ((pw = getpwnam(username)) == NULL)err_quit(errfd, "ERROR: can't find user '%s': getpwnam failed", username);if (setgid(pw->pw_gid) < 0)err_sys_quit(errfd, "ERROR: can't change group id: setgid");if (setuid(pw->pw_uid) < 0)err_sys_quit(errfd, "ERROR: can't change user id: setuid");err_report(errfd, "INFO: changed process user id to '%s'", username);
}/******************************************************************/static void open_log_files(void)
{int fd;char str[32];if (interactive_mode)return;/* Open access log */if (log_access)logbuf_open();/* Open and write pid to pid file */if ((fd = open(PID_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)err_sys_quit(errfd, "ERROR: can't open pid file: open");sprintf(str, "%d\n", (int)getpid());if (write(fd, str, strlen(str)) != strlen(str))err_sys_quit(errfd, "ERROR: can't write to pid file: write");close(fd);/* Open error log file */if ((fd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)err_sys_quit(errfd, "ERROR: can't open error log file: open");errfd = fd;err_report(errfd, "INFO: starting the server...");
}/******************************************************************/static void start_processes(void)
{int i, status;pid_t pid;sigset_t mask, omask;if (interactive_mode) {my_index = 0;my_pid = getpid();return;}for (i = 0; i < vp_count; i++) {if ((pid = fork()) < 0) {err_sys_report(errfd, "ERROR: can't create process: fork");if (i == 0)exit(1);err_report(errfd, "WARN: started only %d processes out of %d", i,vp_count);vp_count = i;break;}if (pid == 0) {my_index = i;my_pid = getpid();/* Child returns to continue in main() */return;}vp_pids[i] = pid;}/** Parent process becomes a "watchdog" and never returns to main().*//* Install signal handlers */Signal(SIGTERM, wdog_sighandler);  /* terminate */Signal(SIGHUP,  wdog_sighandler);  /* restart   */Signal(SIGUSR1, wdog_sighandler);  /* dump info *//* Now go to sleep waiting for a child termination or a signal */for ( ; ; ) {if ((pid = wait(&status)) < 0) {if (errno == EINTR)continue;err_sys_quit(errfd, "ERROR: watchdog: wait");}/* Find index of the exited child */for (i = 0; i < vp_count; i++) {if (vp_pids[i] == pid)break;}/* Block signals while printing and forking */sigemptyset(&mask);sigaddset(&mask, SIGTERM);sigaddset(&mask, SIGHUP);sigaddset(&mask, SIGUSR1);sigprocmask(SIG_BLOCK, &mask, &omask);if (WIFEXITED(status))err_report(errfd, "WARN: watchdog: process %d (pid %d) exited"" with status %d", i, pid, WEXITSTATUS(status));else if (WIFSIGNALED(status))err_report(errfd, "WARN: watchdog: process %d (pid %d) terminated"" by signal %d", i, pid, WTERMSIG(status));else if (WIFSTOPPED(status))err_report(errfd, "WARN: watchdog: process %d (pid %d) stopped"" by signal %d", i, pid, WSTOPSIG(status));elseerr_report(errfd, "WARN: watchdog: process %d (pid %d) terminated:"" unknown termination reason", i, pid);/* Fork another VP */if ((pid = fork()) < 0) {err_sys_report(errfd, "ERROR: watchdog: can't create process: fork");} else if (pid == 0) {my_index = i;my_pid = getpid();/* Child returns to continue in main() */return;}vp_pids[i] = pid;/* Restore the signal mask */sigprocmask(SIG_SETMASK, &omask, NULL);}
}/******************************************************************/static void wdog_sighandler(int signo)
{int i, err;/* Save errno */err = errno;/* Forward the signal to all children */for (i = 0; i < vp_count; i++) {if (vp_pids[i] > 0)kill(vp_pids[i], signo);}/** It is safe to do pretty much everything here because process is* sleeping in wait() which is async-safe.*/switch (signo) {case SIGHUP:err_report(errfd, "INFO: watchdog: caught SIGHUP");/* Reopen log files - needed for log rotation */if (log_access) {logbuf_close();logbuf_open();}close(errfd);if ((errfd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)err_sys_quit(STDERR_FILENO, "ERROR: watchdog: open");break;case SIGTERM:/* Non-graceful termination */err_report(errfd, "INFO: watchdog: caught SIGTERM, terminating");unlink(PID_FILE);exit(0);case SIGUSR1:err_report(errfd, "INFO: watchdog: caught SIGUSR1");break;default:err_report(errfd, "INFO: watchdog: caught signal %d", signo);}/* Restore errno */errno = err;
}/******************************************************************/static void install_sighandlers(void)
{sigset_t mask;int p[2];/* Create signal pipe */if (pipe(p) < 0)err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create"" signal pipe: pipe", my_index, my_pid);if ((sig_pipe[0] = st_netfd_open(p[0])) == NULL ||(sig_pipe[1] = st_netfd_open(p[1])) == NULL)err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create"" signal pipe: st_netfd_open", my_index, my_pid);/* Install signal handlers */Signal(SIGTERM, child_sighandler);  /* terminate */Signal(SIGHUP,  child_sighandler);  /* restart   */Signal(SIGUSR1, child_sighandler);  /* dump info *//* Unblock signals */sigemptyset(&mask);sigaddset(&mask, SIGTERM);sigaddset(&mask, SIGHUP);sigaddset(&mask, SIGUSR1);sigprocmask(SIG_UNBLOCK, &mask, NULL);
}/******************************************************************/static void child_sighandler(int signo)
{int err, fd;err = errno;fd = st_netfd_fileno(sig_pipe[1]);/* write() is async-safe */if (write(fd, &signo, sizeof(int)) != sizeof(int))err_sys_quit(errfd, "ERROR: process %d (pid %d): child's signal"" handler: write", my_index, my_pid);errno = err;
}/******************************************************************* The "main" function of the signal processing thread.*//* ARGSUSED */
static void *process_signals(void *arg)
{int signo;for ( ; ; ) {/* Read the next signal from the signal pipe */if (st_read(sig_pipe[0], &signo, sizeof(int),ST_UTIME_NO_TIMEOUT) != sizeof(int))err_sys_quit(errfd, "ERROR: process %d (pid %d): signal processor:"" st_read", my_index, my_pid);switch (signo) {case SIGHUP:err_report(errfd, "INFO: process %d (pid %d): caught SIGHUP,"" reloading configuration", my_index, my_pid);if (interactive_mode) {load_configs();break;}/* Reopen log files - needed for log rotation */if (log_access) {logbuf_flush();logbuf_close();logbuf_open();}close(errfd);if ((errfd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)err_sys_quit(STDERR_FILENO, "ERROR: process %d (pid %d): signal"" processor: open", my_index, my_pid);/* Reload configuration */load_configs();break;case SIGTERM:/** Terminate ungracefully since it is generally not known how long* it will take to gracefully complete all client sessions.*/err_report(errfd, "INFO: process %d (pid %d): caught SIGTERM,"" terminating", my_index, my_pid);if (log_access)logbuf_flush();exit(0);case SIGUSR1:err_report(errfd, "INFO: process %d (pid %d): caught SIGUSR1",my_index, my_pid);/* Print server info to stderr */dump_server_info();break;default:err_report(errfd, "INFO: process %d (pid %d): caught signal %d",my_index, my_pid, signo);}}/* NOTREACHED */return NULL;
}/******************************************************************* The "main" function of the access log flushing thread.*//* ARGSUSED */
static void *flush_acclog_buffer(void *arg)
{for ( ; ; ) {st_sleep(ACCLOG_FLUSH_INTERVAL);logbuf_flush();}/* NOTREACHED */return NULL;
}/******************************************************************/static void start_threads(void)
{long i, n;/* Create access log flushing thread */if (log_access && st_thread_create(flush_acclog_buffer, NULL, 0, 0) == NULL)err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create"" log flushing thread", my_index, my_pid);/* Create connections handling threads */for (i = 0; i < sk_count; i++) {err_report(errfd, "INFO: process %d (pid %d): starting %d threads"" on %s:%u", my_index, my_pid, max_wait_threads,srv_socket[i].addr, srv_socket[i].port);WAIT_THREADS(i) = 0;BUSY_THREADS(i) = 0;RQST_COUNT(i) = 0;for (n = 0; n < max_wait_threads; n++) {if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL)WAIT_THREADS(i)++;elseerr_sys_report(errfd, "ERROR: process %d (pid %d): can't create"" thread", my_index, my_pid);}if (WAIT_THREADS(i) == 0)exit(1);}
}/******************************************************************/static void *handle_connections(void *arg)
{st_netfd_t srv_nfd, cli_nfd;struct sockaddr_in from;int fromlen;long i = (long) arg;srv_nfd = srv_socket[i].nfd;fromlen = sizeof(from);while (WAIT_THREADS(i) <= max_wait_threads) {cli_nfd = st_accept(srv_nfd, (struct sockaddr *)&from, &fromlen,ST_UTIME_NO_TIMEOUT);if (cli_nfd == NULL) {err_sys_report(errfd, "ERROR: can't accept connection: st_accept");continue;}/* Save peer address, so we can retrieve it later */st_netfd_setspecific(cli_nfd, &from.sin_addr, NULL);WAIT_THREADS(i)--;BUSY_THREADS(i)++;if (WAIT_THREADS(i) < min_wait_threads && TOTAL_THREADS(i) < max_threads) {/* Create another spare thread */if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL)WAIT_THREADS(i)++;elseerr_sys_report(errfd, "ERROR: process %d (pid %d): can't create"" thread", my_index, my_pid);}handle_session(i, cli_nfd);st_netfd_close(cli_nfd);WAIT_THREADS(i)++;BUSY_THREADS(i)--;}WAIT_THREADS(i)--;return NULL;
}/******************************************************************/static void dump_server_info(void)
{char *buf;int i, len;if ((buf = malloc(sk_count * 512)) == NULL) {err_sys_report(errfd, "ERROR: malloc failed");return;}len = sprintf(buf, "\n\nProcess #%d (pid %d):\n", my_index, (int)my_pid);for (i = 0; i < sk_count; i++) {len += sprintf(buf + len, "\nListening Socket #%d:\n""-------------------------\n""Address                    %s:%u\n""Thread limits (min/max)    %d/%d\n""Waiting threads            %d\n""Busy threads               %d\n""Requests served            %d\n",i, srv_socket[i].addr, srv_socket[i].port,max_wait_threads, max_threads,WAIT_THREADS(i), BUSY_THREADS(i), RQST_COUNT(i));}write(STDERR_FILENO, buf, len);free(buf);
}/******************************************************************* Stubs*//** Session handling function stub. Just dumps small HTML page.*/
void handle_session(long srv_socket_index, st_netfd_t cli_nfd)
{static char resp[] = "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n""Connection: close\r\n\r\n<H2>It worked!</H2>\n";char buf[512];int n = sizeof(resp) - 1;struct in_addr *from = st_netfd_getspecific(cli_nfd);if (st_read(cli_nfd, buf, sizeof(buf), SEC2USEC(REQUEST_TIMEOUT)) < 0) {err_sys_report(errfd, "WARN: can't read request from %s: st_read",inet_ntoa(*from));return;}if (st_write(cli_nfd, resp, n, ST_UTIME_NO_TIMEOUT) != n) {err_sys_report(errfd, "WARN: can't write response to %s: st_write",inet_ntoa(*from));return;}RQST_COUNT(srv_socket_index)++;
}/** Configuration loading function stub.*/
void load_configs(void)
{err_report(errfd, "INFO: process %d (pid %d): configuration loaded",my_index, my_pid);
}/** Buffered access logging methods.* Note that stdio functions (fopen(3), fprintf(3), fflush(3), etc.) cannot* be used if multiple VPs are created since these functions can flush buffer* at any point and thus write only partial log record to disk.* Also, it is completely safe for all threads of the same VP to write to* the same log buffer without any mutex protection (one buffer per VP, of* course).*/
void logbuf_open(void)
{}void logbuf_flush(void)
{}void logbuf_close(void)
{}/******************************************************************* Small utility functions*/static void Signal(int sig, void (*handler)(int))
{struct sigaction sa;sa.sa_handler = handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;sigaction(sig, &sa, NULL);
}static int cpu_count(void)
{int n;#if defined (_SC_NPROCESSORS_ONLN)n = (int) sysconf(_SC_NPROCESSORS_ONLN);
#elif defined (_SC_NPROC_ONLN)n = (int) sysconf(_SC_NPROC_ONLN);
#elif defined (HPUX)
#include <sys/mpctl.h>n = mpctl(MPC_GETNUMSPUS, 0, 0);
#elsen = -1;errno = ENOSYS;
#endifreturn n;
}/******************************************************************/
关键字:网站模板怎么打开_江苏市场监督管理局app_seo排名如何_教育培训机构

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: