先放一个整体的MAIN函数
MAIN(goahead, int argc, char **argv, char **envp)
{
char *argp, *home, *documents, *endpoints, *endpoint, *route, *auth, *tok, *lspec;
int argind;
#if WINDOWS
if (windowsInit() < 0) {
return 0;
}
#endif
route = "route.txt";
auth = "auth.txt";
for (argind = 1; argind < argc; argind++) {
argp = argv[argind];
if (*argp != '-') {
break;
} else if (smatch(argp, "--auth") || smatch(argp, "-a")) {
if (argind >= argc) usage();
auth = argv[++argind];
#if ME_UNIX_LIKE && !MACOSX
} else if (smatch(argp, "--background") || smatch(argp, "-b")) {
websSetBackground(1);
#endif
} else if (smatch(argp, "--debugger") || smatch(argp, "-d") || smatch(argp, "-D")) {
websSetDebug(1);
} else if (smatch(argp, "--home")) {
if (argind >= argc) usage();
home = argv[++argind];
if (chdir(home) < 0) {
error("Cannot change directory to %s", home);
exit(-1);
}
} else if (smatch(argp, "--log") || smatch(argp, "-l")) {
if (argind >= argc) usage();
logSetPath(argv[++argind]);
} else if (smatch(argp, "--verbose") || smatch(argp, "-v")) {
logSetPath("stdout:2");
} else if (smatch(argp, "--route") || smatch(argp, "-r")) {
route = argv[++argind];
} else if (smatch(argp, "--version") || smatch(argp, "-V")) {
printf("%s\n", ME_VERSION);
exit(0);
} else if (*argp == '-' && isdigit((uchar) argp[1])) {
lspec = sfmt("stdout:%s", &argp[1]);
logSetPath(lspec);
wfree(lspec);
} else {
usage();
}
}
documents = ME_GOAHEAD_DOCUMENTS;
if (argc > argind) {
documents = argv[argind++];
}
initPlatform();
if (websOpen(documents, route) < 0) {
error("Cannot initialize server. Exiting.");
return -1;
}
#if ME_GOAHEAD_AUTH
if (auth && websLoad(auth) < 0) {
error("Cannot load %s", auth);
return -1;
}
#endif
logHeader();
if (argind < argc) {
while (argind < argc) {
endpoint = argv[argind++];
if (websListen(endpoint) < 0) {
return -1;
}
}
} else {
endpoints = sclone(ME_GOAHEAD_LISTEN);
for (endpoint = stok(endpoints, ", \t", &tok); endpoint; endpoint = stok(NULL, ", \t,", &tok)) {
#if !ME_COM_SSL
if (strstr(endpoint, "https")) continue;
#endif
if (websListen(endpoint) < 0) {
wfree(endpoints);
return -1;
}
}
wfree(endpoints);
}
#if ME_ROM && KEEP
/*
If not using a route/auth config files, then manually create the routes like this:
If custom matching is required, use websSetRouteMatch. If authentication is required, use websSetRouteAuth.
*/
websAddRoute("/", "file", 0);
#endif
#ifdef GOAHEAD_INIT
/*
Define your init function in main.me goahead.init, or
configure with DFLAGS=GOAHEAD_INIT=myInitFunction
*/
{
extern int GOAHEAD_INIT();
if (GOAHEAD_INIT() < 0) {
exit(1);
}
}
#endif
#if ME_UNIX_LIKE && !MACOSX
/*
Service events till terminated
*/
if (websGetBackground()) {
if (daemon(0, 0) < 0) {
error("Cannot run as daemon");
return -1;
}
}
#endif
websServiceEvents(&finished);
logmsg(1, "Instructed to exit");
websClose();
#if WINDOWS
windowsClose();
#endif
return 0;
}
(1)读取入参
主函数的入参提示是:
static void usage(void) {
fprintf(stderr, "\n%s Usage:\n\n"
" %s [options] [documents] [[IPaddress][:port] ...]\n\n"
" Options:\n"
#if ME_GOAHEAD_AUTH
" --auth authFile # User and role configuration\n"
#endif
#if ME_UNIX_LIKE && !MACOSX
" --background # Run as a Unix daemon\n"
#endif
" --debugger # Run in debug mode\n"
" --home directory # Change to directory to run\n"
" --log logFile:level # Log to file file at verbosity level\n"
" --route routeFile # Route configuration file\n"
" --verbose # Same as --log stdout:2\n"
" --version # Output version information\n\n",
ME_TITLE, ME_NAME);
exit(-1);
}
这意味着入参顺序必须是带–参数的选项,之后是文件路径,ip和端口号。
所以[option]部分的入参读取代码为
之后是对[documents]和[ip:port]入参的读取
此部分讲解中对与初始化平台和初始化服务器的部分比较简略,现在开始详细解释。
2、初始化平台
static void initPlatform(void)
{
#if ME_UNIX_LIKE
signal(SIGTERM, sigHandler);
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
#elif ME_WIN_LIKE
_fmode=_O_BINARY;
#endif
}
#if ME_UNIX_LIKE
static void sigHandler(int signo)
{
finished = 1;
}
#endif
以上是初始化平台的函数具体内容。
SIGTERM: 请求中止进程,kill命令缺省发送**
所以这个平台初始化做的内容是程序被中止时,将静态全局变量finished变量置为1。这个变量下面会讲到,这里留意一下。
在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用signal(SIGPIPE, SIG_IGN);即可安全的屏蔽SIGPIPE:
3、服务端初始化
服务端初始化内容太多了,下篇再写吧。