正在移植Goahead webserver,看到一篇在VxWorks上移植的文章

以前在交换机上做过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还会有什么问题,祝自己好运把

你可能感兴趣的:(Web,struct,socket,cgi,input,makefile)