1、45:45 GMTServer: BWS/1.0ContentLength: 9888ContentType: text/html;charset=gbk(数据 数据 数据 数据 数据)2 实现流程嵌入式Web服务器的实现流程如图1所示。一个简单的嵌入式Web服务器的功能是接收Client发送的请求并响应,并根据Client的请求向Client传送所需内容。获取Server当前目录文件列表:将Server当前目录下所有文件的信息发送给Client,信息包括:文件名、日期、大小;获取指定文件:将Client请求的文件发送给Client;获取HTML 类型文件:将Client请求的HTML 类型文
2、件发送给Client;获取纯文本文件:将Client请求的纯文本发送给Client;获取JPG 图像文件:将Client请求的JPG 图像文件发送给Client;获取GIF 图像文件:将Client请求的GIF 图像文件发送给Client;解析Client请求:分析Client的请求,将请求信息解析为几个变量,如:请求的命令、文件名、文件类型。3 主要代码2 int PrintHeader(FILE *f, int content_type) /发送HTTP协议数据头3 5 fprintf(f,HTTP/1.0 200 OKn); /服务器回应http协议数据头的状态行;发送请求成功;6 sw
3、itch (content_type) 8 case t: fprintf(f,Content-type: text/plainn break;/发送纯文本文件信息;11 case g image/gifn/发送gif格式图片信息;14 case j image/jpegn/发送gpeg格式图片信息;17 case h text/htmln/发送html信息;20 21 fprintf(f,Server: embedded-httpd 0.1n /发送服务器版本信息;22 fprintf(f,Expires: 0n /发送文件永不过期信息;23 fprintf(f,n return(0);26
4、 28 int DoJpeg(FILE *f, char *name) /对jpeg格式的文件进行处理;29 30 char *buf; FILE * infile; int count;34 if (!(infile = fopen(name, r) /通过文件名打开一个文件,只读属性;36 fprintf(stderr, Unable to open JPEG file %s, %dn, name, errno);37 fflush(f); return -1;40 42 PrintHeader(f, /发送j类型的http协议数据头信息;45 copy(infile,f); /* pri
5、nts the page */48 fclose(infile); return 0;52 54 int DoGif()、DoDir ()、DoHTML ()、DoText ()类似DoJpeg()161 int ParseReq(FILE *f, char *r)162 163 char *bp; struct stat stbuf; char * arg; char * c; int e; int raw;174 while(*(+r) != /*skip non-white space*/ /判断buf中的内容是否为空跳过非空白;175 while(isspace(*r) r+; /判断
6、r所在位置的字符是否为空格,若为空格则r指向下一个字符;178 while (*r = /) r+; /判断r所在位置的字符是否为/若为空格则r指向下一个字符;180 bp = r; /将r所指向的内容赋值给bp bp指向/之后的内容;img/baidu_sylogo1.gif HTTP/1.1rn182 while(*r & (*(r) !) &?) r+; /当r不为空,并求 r不为?时r指向下一个字符189 if (*r = ) /判断 r是否为 ?若为?则执行以下语句;191 char * e; *r = 0; arg = r+1;194 if (e = strchr(arg,) *e
7、 = 0; /如果arg为空则将arg所在位置置为0复制给e;198 else / 如果当前r指向字符不为 , 将r指向字符置为 ,200 arg = 0;202 204 c = bp;207 if (c0 = 0x20) c0=. c1= /判断c中的字符内容是否为空格;若为空格212 if(c0 = ) strcat(c,. /若 c中为0则将.链接在c后214 if (c & !stat(c, &stbuf) /通过文件名c获取文件信息,并保存在stbuf中218 if (S_ISDIR(stbuf.st_mode) /判断结果是否为特定的值219 char * end = c + st
8、rlen(c); /end指向c的末尾;221 strcat(c, /index.html /将/index.html加到c后,后面追加0;222 if (!stbuf) /通过文件名c获取文件信息,并保存在stbuf中 ;成功返回0223 DoHTML(f, c); /对html文件进行处理;225 else *end = DoDir(f,c); /若c中没有/index.html则跳到目录处理代码处执行231 else if (!strcmp(r - 4, .gif) /判断r中的后四个字符,即判断文件类型;233 DoGif(f,c); /若是 gif格式的文件则跳转到DoGif对其进行
9、处理;234 else if (!.jpg) | !strcmp(r - 5, .jpeg)235 DoJpeg(f,c); /若是 jpg或jpeg格式的文件则跳转到DoJpeg对其进行处理236 else if (!.htm.html237 DoHTML(f,c); /若是 htm格式的文件则跳转到DoHTML处对其进行处理238 else DoText(f,c);/若是 纯文本格式的文件则跳转到DoText对其进行处理240 else242 PrintHeader(f, /发送h类型的http协议数据头244 fprintf(f, /打印出错信息245 fprintf(f, The re
10、quested URL was not found on this servern247 return 0;249 257 int HandleConnect(int fd)258 259 FILE *f; char buf160; char buf1160;264 f = fdopen(fd,a+ /以文件描述符的形式打开文件; a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。272 setbuf(f, 0); /将关闭缓冲区;276 if (!fgets(buf, 150, f) /直接通过f读取150个字
11、符放入以buf为起始地址中,不成功时返回0则打印出错信息;否则fgets成功返回函数指针打印buf的内容;277 fprintf(stderr, httpd: Error reading connection, error %dn, errno);278 fclose(f);281 288 referrer0 = content_length = -1;293 while (fgets(buf1, 150, f) & (strlen(buf1) 2) /直接通过f读取150个字符放入以buf1为起始地址的空间中;298 if (!strncasecmp(buf1, Referer:, 8) /
12、将buf1中的前八个字符与字符串Referer:若相等则将将指针指向buf1中的Referer:之后;299 char * c = buf1+8;300 while (isspace(*c) c+; /判断c处是否为空格若为空格则c指向下一个字符;302 strcpy(referrer, c); /将c所指的内存单元的内容复制到referrer数组中;303 else if (!Referrer:, 9) /将buf1中的前九个字符与字符串Referrer:若相等则将将指针指向buf1中的Referrer:305 char * c = buf1+8; char * c = buf1+9;307
13、 while (isspace(*c) c+;309 strcpy(referrer, c);310 else if (!Content-length:, 15) ) /将buf1中的前15个字符与字符串Content-length:若相等则将将指针指向buf1中的Content-length:313 content_length = atoi(buf1+15); /atoi类型转换将buf1中的内容转换为整型赋值给content_length;314 315 324 ParseReq(f, buf); /解析客户请求函数;327 fflush(f); fclose(f); return 1;
14、331 335 void* key(void* data) 从键盘输入一个字符,若输入q则退出程序; 349 int main(int argc, char *argv)350 351 int fd, s; int len; volatile int true = 1;354 struct sockaddr_in ec, server_sockaddr; /定义结构体变量;357 pthread_t th_key; void * retval;365 chroot(HTTPD_DOCUMENT_ROOT); /改变根目录;在makefile文件中指定;366 printf(starting h
15、ttpd.n /打印启用服务器程序信息;367 printf(press q to quit.n370 if (argc 1 &strcmp(argv1, -i) / 若argv1等于-i strcmp返回0 并且 argc大于1 执行if下的语句快即关闭文件描述符;372 fclose(stderr); HandleConnect(0); /向HandleConnect函数传入0文件描述符即标准输入;374 exit(0);375 388 server_sockaddr.sin_family = AF_INET;389 server_sockaddr.sin_port = htons(SER
16、VER_PORT);390 server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);392 if(bind(s, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr) = -1) 395 perror(Unable to bind socket exit(1);397 399 if(listen(s, 8*3) = -1) perror(Unable to listenexit(4);405 pthread_create(&th_key, NULL, key, 0); /创建线程
17、;407 printf(wait for connection.n408 while (1) len = sizeof(ec);411 if(fd = accept(s, (void *)&ec, &len) = -1) /接受客户机的请求,与客户机建立链接;412 exit(5); close(s);415 HandleConnect(fd); /处理链接函数调用fd 为客户连接文件描述符;417 418 pthread_join(th_key, &retval); /以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果进程已经结束,那么该函数会立即返回。成
18、功返回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).
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1