主要分为访问网页文件以及接口的调用逻辑
首先网页访问流程:网页访问事件注册 程序中需要返回html网页文件已经相关的图片、css等资源
// fileHandler函数判断和处理需要返回到浏览器的html文件数据
static bool fileHandler(Webs *wp)
{
WebsFileInfo info;
char *tmp, *date;
ssize nchars;
int code;
int result;
assert(websValid(wp));
assert(wp->method);
assert(wp->filename && wp->filename[0]);
printf("%s(%d)filename=%s\n", __FILE__, __LINE__, wp->filename); // filename=/web/index.html
printf("%s(%d)method=%s\n", __FILE__, __LINE__, wp->method); // method=GET
/*
If the file is a directory, redirect using the nominated default page
如果这里的文件路径是一个目录,则使用指定的默认(html)页面
*/
if (websPageIsDirectory(wp)) { // 返回值 0=文件, 1=目录
nchars = strlen(wp->path);
if (wp->path[nchars - 1] == '/' || wp->path[nchars - 1] == '\\') {
wp->path[--nchars] = '\0';
}
tmp = sfmt("%s/%s", wp->path, websIndex);
websRedirect(wp, tmp);
wfree(tmp);
return 1;
}else{
printf("%s(%d)call websPageIsDirectory %s, >>> no a directory\n", __FILE__, __LINE__, wp->filename);
}
if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) <= 0) { //这里在移植到wince的过程有所改动,如果打不开(html)文件返回0
websError(wp, HTTP_CODE_NOT_FOUND, "Cannot open document for: %s", wp->path);
return 1;
}
if (websPageStat(wp, &info) < 0) { // 这里使用了GetFileAttributesEx(与ce系统相关接口)获取文件大小 修改时间等属性
websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat page for URL");
return 1;
}
code = 200;
if (wp->since && info.mtime <= wp->since) {
// 比较html文件的时间 如果不合法 则返回304
code = 304;
info.size = 0;
}
websSetStatus(wp, code);
websWriteHeaders(wp, info.size, 0);
if ((date = websGetDateString(&info)) != NULL) {
websWriteHeader(wp, "Last-Modified", "%s", date);
wfree(date);
}
websWriteEndHeaders(wp);
/*
All done if the browser did a HEAD request 没有头部请求时调用websDone返回
*/
if (smatch(wp->method, "HEAD")) {
websDone(wp);
return 1;
}
if (info.size > 0) {
websSetBackgroundWriter(wp, fileWriteEvent);
} else {
websDone(wp);
}
return 1;
}
goahead作为一个web服务器端 需要等待浏览器端的接入 所以需要等待事件的发生 这里使用了阻塞的方式进行事件等待 具体流程如下
PUBLIC void websServiceEvents(int *finished){
WebsTime delay, nextEvent;
if (finished) {
*finished = 0;
}
delay = 0;
while (!finished || !*finished) {
if (socketSelect(-1, delay)) {
socketProcess();
}
delay = MAXINT;
nextEvent = websRunEvents();
delay = min(delay, nextEvent);
}
}
API注释翻译:
基本事件循环,socketready返回true当一个套接字准备好服务。socketselect将阻塞直到事件发生。socketprocess实际上为服务进程
websServiceEvents函数在main函数的之后调用 处于循环状态 程序不会退出 平时处于阻塞状态等待浏览器端发送请求并进行处理 处理完成进入下一轮等待