以前在交换机上做过web cgi的程序,是在51系统上面做的,记得原理都是相似的,把页面做成二进制数组,不过现在有些忘了,只好再熟悉一遍。以下来自http://ajonbin.spaces.live.com/blog/cns!5619a73390dcd51e!132.entry,若有版权问题,请通知我。
GoAhead, vxworks 和 CGI
最 近在做监控的客户端,Vxworks下。基本上拿以前的IPTV的代码,改吧改吧,就OK了。不过有个挺大的问题,IPTV是有界面的,通过遥控器控制。 通过遥控器控制毕竟还是麻烦点,要是再输入文字的话就更让人抓狂了。监控客户端很简单,不要复杂的操作界面,所以就考虑在client里内嵌一个web server。所有的操作和配置都通过网页进行,实在是个不错的选择啊。
http://www.goahead.com)的东东不错啊,支持多平台的。就喜欢这样的。
载了个2.1.8的版本,在window上先编译了一下,运行,访问,一切OK。
开始移植到vxworks。它有个vxworks的makefile 稍微改一下就好了
CC = ecc
LINK = eld
AR = ar
CFLAGS += -DWEBS_PAGE_ROM -DWEBS -DUEMF -DOS="VXWORKS" -DVXWORKS $(UMSW) $(DASW) -Wall $(SSLSW) -I$(RTOS_INCLUDES) -I../
加上
comp:
ecc -I../ -I./ -o webcomp $(CFLAGS) ../webcomp.c
find ../web -name "*.*" > websfile
-DWEBS_PAGE_ROM 这个宏一定要加上。
goahead可以将网页文件打包成C语言的数组,这样适合没有硬盘的嵌入式系统。
再来说说怎么打包web文件。已他自带的web目录为例。
在./win/目录下,有个webcomp.dsw工程,先编个可执行文件webcomp.exe
然后运行 webcomp.exe ../web websfile > webrom.c
其中websfile是在在makefile中
find ../web -name "*.*" > websfile
生成的,也就是web页面目录里的文件列表,
../web是此文件列表里的文件前缀,大家看看websfile就懂了。
webrom.c就是生成的网页数据文件。
然后把webrom.c替换掉原有的webrom.c
在./vxwokrs里的webmain函数去掉入参。
再修改web根目录
MAIN.C : L 172 sprintf(webdir, "%s/%s", ROOT_DIR, rootWeb);
改为
sprintf(webdir, "./"); //这个可是反复试验得出的结论啊,辛苦辛苦
再编译webs,生成了libwebs.a
再在client里添加
taskSpawn("websvxmain",100,0,1024*100,websvxmain,0,0,0,0,0,0,0,0,0,0);
IE访问一把,OK了。
webserver是跑起来,不过webserver和client程序之间怎么通信是一个大问题啊!
问了不少人,搜个不少遍,也没什么好的办法,本来是想webserver能不能直接调用C函数,这个好像比较困难。
最后决定用CGI程序,利用socket在video client和web server之间通信。
就是在CGI程序里创建SOCKET,和vidoe client通信。
先在windows下做试验
又花了不少时间把CG搞通了,开始写socket。
代码如下
html页面:
< HTML >
< FORM ACTION="/cgi-bin/multi.exe" METHOD=GET >
< P >输入数据得到结构< INPUT NAME="m" SIZE="5" >
< INPUT NAME="n" SIZE="5 ">< BR >
< INPUT TYPE="SUBMIT" VALUE=“确定" >
< /FORM >
< /HTML >
CGI程序
int main(void)
{
char *data;
long m,n;
int i = 0;
//生成表单
printf("%s%c%c ","Content-Type:text/html;charset=gb2312",13,10);
printf("<HTML>");
printf("<TITLE>乘法结果</TITLE>/n");
printf("<H3>乘法结果</H3>/n");
data = getenv("QUERY_STRING");
if(data == NULL)
{
printf("<P>错误!数据没有被输入或者数据传输有问题/n");
}
else if(sscanf(data,"m=%ld&n=%ld",&m,&n)!=2)
{
printf("<P>错误!输入数据非法。表单中输入的必须是数字。/n");
}
else
{
printf("<P>%ld和%ld的成绩是:%ld。/n",m,n,m*n);
}
// 发送数据
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
SOCKET s_send;
struct sockaddr_in localAddr;
struct sockaddr_in peer_addr;
char buf[4] = {0};
wVersionRequested = MAKEWORD( 2, 0 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf("start up error/n");
return -1;
}
s_send = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (s_send == -1)
{
int i = GetLastError();
printf("create error %d/n",i);
return -1;
}
printf("s_send = %d/n",s_send);
memset(&localAddr, 0, sizeof(struct sockaddr_in));
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(1600);
localAddr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind(s_send,(struct sockaddr*)&localAddr,sizeof(struct sockaddr_in)) == -1)
{
printf("bind error %d/n",GetLastError());
return -1;
}
memset(&peer_addr, 0, sizeof(struct sockaddr_in));
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons(11000);
peer_addr.sin_addr.s_addr = inet_addr("172.16.66.85");
sendto(s_send,buf,4,0,(struct sockaddr*)&peer_addr,sizeof(peer_addr));
printf("send /n");
closesocket(s_send);
}
printf("</HTML>");
return 0;
}
编译生成multi.exe放在CGI-BIN目录下。
结构发现create socket出错了,错误代码是10106 无法加载或初始化请求的服务提供程序。
俺的神呀!
还没碰到这中问题啊。
继续google,得到了些提示,好像是环境变量没设置
加上一句
_putenv("SYSTEMROOT=C://WINDOWS");
啊,完美了!
工作还在继续...问题还有很多,不知道在vxworks还会有什么问题,祝自己好运把