嵌入式Web服务器设计与实现Word格式文档下载.docx
《嵌入式Web服务器设计与实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《嵌入式Web服务器设计与实现Word格式文档下载.docx(7页珍藏版)》请在冰豆网上搜索。
45:
45GMT
Server:
BWS/1.0
ContentLength:
9888
ContentType:
text/html;
charset=gbk
(数据数据数据数据数据…………)
2实现流程
嵌入式Web服务器的实现流程如图1所示。
一个简单的嵌入式Web服务器的功能是接收Client发送的请求并响应,并根据Client的请求向Client传送所需内容。
①获取Server当前目录文件列表:
将Server当前目录下所有文件的信息发送给Client,信息包括:
文件名、日期、大小;
②获取指定文件:
将Client请求的文件发送给Client;
③获取HTML类型文件:
将Client请求的HTML类型文件发送给Client;
④获取纯文本文件:
将Client请求的纯文本发送给Client;
⑤获取JPG图像文件:
将Client请求的JPG图像文件发送给Client;
⑥获取GIF图像文件:
将Client请求的GIF图像文件发送给Client;
⑦解析Client请求:
分析Client的请求,将请求信息解析为几个变量,如:
请求的命令、文件名、文件类型。
3主要代码
2intPrintHeader(FILE*f,intcontent_type)//发送HTTP协议数据头
3{
5fprintf(f,"
HTTP/1.0200OK\n"
);
//服务器回应http协议数据头的状态行;
发送请求成功;
6switch(content_type){
8case'
t'
:
fprintf(f,"
Content-type:
text/plain\n"
break;
//发送纯文本文件信息;
11case'
g'
image/gif\n"
//发送gif格式图片信息;
14case'
j'
image/jpeg\n"
//发送gpeg格式图片信息;
17case'
h'
text/html\n"
//发送html信息;
20}
21fprintf(f,"
Server:
embedded-httpd0.1\n"
//发送服务器版本信息;
22fprintf(f,"
Expires:
0\n"
//发送文件永不过期信息;
23fprintf(f,"
\n"
return(0);
26}
28intDoJpeg(FILE*f,char*name)//对jpeg格式的文件进行处理;
29{
30char*buf;
FILE*infile;
intcount;
34if(!
(infile=fopen(name,"
r"
))){//通过文件名打开一个文件,只读属性;
36fprintf(stderr,"
UnabletoopenJPEGfile%s,%d\n"
,name,errno);
37fflush(f);
return-1;
40}
42PrintHeader(f,'
//发送j类型的http协议数据头信息;
45copy(infile,f);
/*printsthepage*/
48fclose(infile);
return0;
52}
54intDoGif()、DoDir()、DoHTML()、DoText()类似DoJpeg()
161intParseReq(FILE*f,char*r)
162{
163char*bp;
structstatstbuf;
char*arg;
char*c;
inte;
intraw;
174while(*(++r)!
='
'
/*skipnon-whitespace*///判断buf中的内容是否为空跳过非空白;
175while(isspace(*r))r++;
//判断r所在位置的字符是否为空格,若为空格则r指向下一个字符;
178while(*r=='
/'
)r++;
//判断r所在位置的字符是否为/若为空格则r指向下一个字符;
180bp=r;
//将r所指向的内容赋值给bpbp指向/之后的内容;
img/baidu_sylogo1.gifHTTP/1.1\r\n
182while(*r&
&
(*(r)!
)&
?
'
))r++;
//当r不为空,并求r不为?
时r指向下一个字符
189if(*r=='
){//判断r是否为?
若为?
则执行以下语句;
191char*e;
*r=0;
arg=r+1;
194if(e=strchr(arg,'
)){*e='
\0'
;
}//如果arg为空则将arg所在位置置为\0复制给e;
198}else{//如果当前r指向字符不为'
,将r指向字符置为'
,
200arg=0;
202}
204c=bp;
207if(c\[0\]==0x20){c\[0\]='
.'
c\[1\]='
}//判断c中的字符内容是否为空格;
若为空格
212if(c\[0\]=='
)strcat(c,"
."
//若c中为\0则将.链接在c后
214if(c&
!
stat(c,&
stbuf)){//通过文件名c获取文件信息,并保存在stbuf中
218if(S_ISDIR(stbuf.st_mode)){//判断结果是否为特定的值
219char*end=c+strlen(c);
//end指向c的末尾;
221strcat(c,"
/index.html"
//将/index.html加到c后,后面追加\0;
222if(!
stbuf))//通过文件名c获取文件信息,并保存在stbuf中;
成功返回0
223{DoHTML(f,c);
//对html文件进行处理;
225}else{*end='
}DoDir(f,c);
//若c中没有/index.html则跳到目录处理代码处执行
231}elseif(!
strcmp(r-4,"
.gif"
))//判断r中的后四个字符,即判断文件类型;
233DoGif(f,c);
//若是gif格式的文件则跳转到DoGif对其进行处理;
234elseif(!
.jpg"
)||!
strcmp(r-5,"
.jpeg"
))
235DoJpeg(f,c);
//若是jpg或jpeg格式的文件则跳转到DoJpeg对其进行处理
236elseif(!
.htm"
.html"
237DoHTML(f,c);
//若是htm格式的文件则跳转到DoHTML处对其进行处理
238elseDoText(f,c);
//若是纯文本格式的文件则跳转到DoText对其进行处理
240}else{
242PrintHeader(f,'
//发送h类型的http协议数据头
244fprintf(f,"
//打印出错信息
245fprintf(f,"
TherequestedURLwasnotfoundonthisserver\n"
247}return0;
249}
257intHandleConnect(intfd)
258{
259FILE*f;
charbuf\[160\];
charbuf1\[160\];
264f=fdopen(fd,"
a+"
//以文件描述符的形式打开文件;
a+以附加方式打开可读写的文件。
若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
272setbuf(f,0);
//将关闭缓冲区;
276if(!
fgets(buf,150,f)){//直接通过f读取150个字符放入以buf为起始地址中,不成功时返回0则打印出错信息;
否则fgets成功返回函数指针打印buf的内容;
277fprintf(stderr,"
httpd:
Errorreadingconnection,error%d\n"
,errno);
278fclose(f);
281}
288referrer\[0\]='
content_length=-1;
293while(fgets(buf1,150,f)&
(strlen(buf1)>
2)){//直接通过f读取150个字符放入以buf1为起始地址的空间中;
298if(!
strncasecmp(buf1,"
Referer:
"
,8)){//将buf1中的前八个字符与字符串Referer:
若相等则将将指针指向buf1中的Referer:
之后;
299char*c=buf1+8;
300while(isspace(*c))c++;
//判断c处是否为空格若为空格则c指向下一个字符;
302strcpy(referrer,c);
//将c所指的内存单元的内容复制到referrer数组中;
303}elseif(!
Referrer:
,9)){//将buf1中的前九个字符与字符串Referrer:
若相等则将将指针指向buf1中的Referrer:
305char*c=buf1+8;
char*c=buf1+9;
307while(isspace(*c))c++;
309strcpy(referrer,c);
310}elseif(!
Content-length:
,15)){)){//将buf1中的前15个字符与字符串Content-length:
若相等则将将指针指向buf1中的Content-length:
313content_length=atoi(buf1+15);
//atoi类型转换将buf1中的内容转换为整型赋值给content_length;
314}
315}
324ParseReq(f,buf);
//解析客户请求函数;
327fflush(f);
fclose(f);
return1;
331}
335void*key(void*data){从键盘输入一个字符,若输入q则退出程序;
}
349intmain(intargc,char*argv\[\])
350{
351intfd,s;
intlen;
volatileinttrue=1;
354structsockaddr_inec,server_sockaddr;
//定义结构体变量;
357pthread_tth_key;
void*retval;
365chroot(HTTPD_DOCUMENT_ROOT);
//改变根目录;
在makefile文件中指定;
366printf("
startinghttpd...\n"
//打印启用服务器程序信息;
367printf("
pressqtoquit.\n"
370if(argc>
1&
strcmp(argv\[1\],"
-i"
)){//若argv\[1\]等于-istrcmp返回0并且argc大于1执行if下的语句快即关闭文件描述符;
372fclose(stderr);
HandleConnect(0);
//向HandleConnect函数传入0文件描述符即标准输入;
374exit(0);
375}
388server_sockaddr.sin_family=AF_INET;
389server_sockaddr.sin_port=htons(SERVER_PORT);
390server_sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
392if(bind(s,(structsockaddr*)&
server_sockaddr,sizeof(server_sockaddr))==-1){
395perror("
Unabletobindsocket"
exit
(1);
397}
399if(listen(s,8*3)==-1){perror("
Unabletolisten"
exit(4);
405pthread_create(&
th_key,NULL,key,0);
//创建线程;
407printf("
waitforconnection.\n"
408while
(1){len=sizeof(ec);
411if((fd=accept(s,(void*)&
ec,&
len))==-1){//接受客户机的请求,与客户机建立链接;
412exit(5);
close(s);
415HandleConnect(fd);
//处理链接函数调用fd为客户连接文件描述符;
417}
418pthread_join(th_key,&
retval);
//以阻塞的方式等待thread指定的线程结束。
当函数返回时,被等待线程的资源被收回。
如果进程已经结束,那么该函数会立即返回。
成功返回0;
该语句不会执行到;
420}
嵌入式Web服务器的程序算法流程如图2所示。
4测试
打开Web浏览器,在地址栏输入开发板的IP地址,即可看到嵌入式Web服务器返回的主页面。
5结语
本文实现了嵌入式Web服务器的基本功能,在此基础上,可以实现其它实用功能,比如:
扩展一个监视功能,在浏览器端监视开发板上的采集数据;
可以使用仿真模拟采集数据,使在客户端浏览器中的显示数据不断变化。
参考文献:
\[1\]车飞锋,孟开元,曹庆年.基于ARM的嵌入式Web服务器的研究与实现\[J\].微计算机信息,2008(26).
\[2\]杨林楠,李红刚,张素萍,等.基于ARM9的嵌入式Web服务器研究\[J\].计算机测量与控制,2008(12).
\[3\]王莉,周伟.基于ARM的嵌入式Web服务器设计\[J\].计算机工程与应用,2012(14).