goahead为一款轻量级的设备内嵌web,其占用内存少并且功能强大,本专栏基于goahead动态库实现简单的webapp开发。
1、下载goahead,本文基于goahead-5.1.2
2、make进行编译,个人基于Linux Ubuntu开发,因此编译成功后会在build/linux-x64-default/bin/目录下包含动态库,秘钥,以及可执行程序。在build/linux-x64-default/inc/目录下包含了头文件。
准备工作
新建一个目录,新建目录结构如下所示。
目录中新建include ,将build/linux-x64-default/inc中的头文件拷贝到include目录中。
目录lib,将build/linux-x64-default/bin中的libgo.so拷贝到lib中。
目录web_cfg,用于存放auth.txt和route.txt文件,auth用来存放用户信息,route用来存放一些uri以及handler以及认证信息如:auth=digest,文件具体详细内容后边我们进行介绍,目前可以先创建这两个文件,使其内容为空即可。
目录web,用于存放web页面相关的代码。
self.crt和self.key为私钥和证书,自己可以通过加密工具生成,也可以直接将编译后产生的文件直接拷贝过来。
目录src用于存放我们自己的源程序代码。
修改代码
修改route.txt ,在route.txt文件中增加如下代码:
route uri=/
goahead_test001.c
#include "goahead.h"
#include "js.h"
/*******/
static int finished = 0;
static void sig_handler(int signo)
{
finished =1;
}
void initPlatform(void)
{
signal(SIGINT,sig_handler);
signal(SIGTERM,sig_handler);
signal(SIGKILL,sig_handler);
}
int main()
{
char *route;
char *auth;
char *documents;
char *endpoints,*endpoint;
char *tok;
route = "web_cfg/route.txt";
auth = "web_cfg/auth.txt";
documents = ME_GOAHEAD_DOCUMENTS;
//init
initPlatform();
if(websOpen(documents,route) < 0){
printf("websOpen fail\n");
return -1;
}
if(websLoad(auth) < 0){
printf("websLoad auth fail\n");
return -1;
}
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 (websGetBackground()) {
if (daemon(0, 0) < 0) {
error("Cannot run as daemon");
return -1;
}
}
websServiceEvents(&finished);
websClose();
return 0;
}
web目录下增加第一个现实文件index.html,index.html中现“This is first web page”
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home Page</title>
</head>
<body>
<p>This is first web page.<p/>
</body>
</html>
Makefile根据代码目录修改
SOURCE = $(wildcard ./src/test001/*.c) #获取所有的.c文件
OBJ = $(patsubst %.c, %.o, $(SOURCE)) #将.c文件转为.o文件
INCLUDES = -I./include #头文件路径
LIBS = -lgo #库文件名字
LIB_PATH = -L./lib #库文件地址
CFLAGS = -Wall -c #编译标志位
TARGET = goahead_test
CC = gcc
$(TARGET): $(OBJ)
$(CC) $(OBJ) $(LIB_PATH) $(LIBS) -o $(TARGET)
%.o: %.c
$(CC) $(INCLUDES) $(DEBUG) $(CFLAGS) $< -o $@
.PHONY: clean
clean:
rm -rf $(OBJ) $(TARGET)
对代码进行整体编译,并执行程序,通过http://localhost进行访问,可以看到web界面现实“This is first web page” 也就是index.html文件中的内容。
接下来我们分析几个函数功能。
代码分析
1、初始化
websOpen(documents,route)
websOpen传入两个行参,documents赋值为ME_GOAHEAD_DOCUMENTS,而改宏定义是在是在头文件中me.h中定义,#define ME_GOAHEAD_DOCUMENTS "web"也就是说改宏定义是传入我们web资源的相对路径,也就是当前目录下web目录。route是相对路径route.txt的相对路径。
在websOpen初始化中通过websSetDocuments函数设置web路径,而通过websGetDocuments获取传入的web路径,代码在file.c中
websLoad加载route.txt文件中的内容。
2、监听
监听端口代码是通过解析ME_GOAHEAD_LISTEN字符串,ME_GOAHEAD_LISTEN字符串在me.h中定义其具体内容为:#define ME_GOAHEAD_LISTEN "http://*:80,https://*:443",也就是说默认http监听80端口,https为443端口。通过解析字符串然后调用websListen对端口进行监听,在websListen函数中,socketParseAddress(endpoint, &ip, &port, &secure, 80)解析ip 端口,socketListen(ip, port, websAccept, 0)进行监听,其中websAccept,为回调函数,服务器与客户端连接。
3、处理流程
websServiceEvents为事件处理函数,通过socketSelect和socketProcess实现事件触发及事件处理过程。socketSelect等待一个链接时候可读或者可写,其中finished为0标志可以对事件进行处理,1表示退出