WEB服务器nullnull1. WEB服务器的工作原理 请求响应服务器客户机WEB
文档WEB
文档
副本只要在嵌入式设备中有一个微型Web服务器, 就可以使用任意一
种Web浏览器接收和发送信息。这种基于Internet的方式使得我们
可以在世界任何一个地方都能够控制它,只要它连入Internet 。对于嵌入式Web服务器的研究和应用,是很有意义的。它为我们远
程管理、控制和监测各种各样设备提供了一个很好的途径。3.3 嵌入式系统WEB服务器的程序设计null最基本的WEB服务器采用HTTP协议(超文本传输协议)
可以以文本、超...
nullnull1. WEB服务器的工作原理 请求响应服务器客户机WEB
文档WEB
文档
副本只要在嵌入式设备中有一个微型Web服务器, 就可以使用任意一
种Web浏览器接收和发送信息。这种基于Internet的方式使得我们
可以在世界任何一个地方都能够控制它,只要它连入Internet 。对于嵌入式Web服务器的研究和应用,是很有意义的。它为我们远
程管理、控制和监测各种各样设备提供了一个很好的途径。3.3 嵌入式系统WEB服务器的程序设计null最基本的WEB服务器采用HTTP
(超文本传输协议)
可以以文本、超文本、图形、音频、视频形式传输数据使用HTTP协议可以在客户端和服务器之间以非常简单
的方式传输数据,客户端发出请求,服务器返回响应
给客户端。nullWEB服务器的应用——智能家居远程监控系统2.简单web服务器的系统分析与程序设计2.简单web服务器的系统分析与程序设计功能需求
数据流图
系统结构图
接口程序设计
模块程序设计功能需求功能需求获取服务器当前目录文件列表
获取指定文件
获取HTML类型文件
获取纯文本文件
获取JPG图像文件
获取GIF图像文件
解析用户请求数据流程图 数据流程图 系统结构图 系统结构图 客户连接处理过程 客户连接处理过程 主程序设计主程序设计功能说明 系统的总入口,也是系统的主控制函数。完成如下功能:
建立环境设置。
设置信号处理方式。
建立侦听TCP流方式SOCKET并绑定80端口。
建立连接侦听及客户连接处理调用主循环。客户连接处理程序客户连接处理程序功能说明 用于初步处理客户的连接请求,并将请求信息传递给客户请求解析函数处理。
客户请求解析处理程序 客户请求解析处理程序 功能说明 用于解析客户的请求,并根据请求信息调用相应的函数进行请求处理。发送HTTP协议数据头程序 发送HTTP协议数据头程序 功能说明
根据参数的不同,发送不同的HTTP协议头信息。
算法
函数定义为:int PrintHeader(FILE *f, int content_type)
发送请求成功信息:HTTP/1.0 200 OK。
根据文档类型发送相应的信息
发送服务器信息
发送文件接口程序设计接口程序设计客户连接处理
函数名:int HandleConnect(int fd)
解析客户请求
函数名:int ParseReq(FILE *f, char *r)
发送HTTP协议数据头
函数名:int PrintHeader(FILE *f, int content_type)
发送当前目录文件列表信息
函数名:int DoDir(FILE *f, char *name)
null
发送HTML文件内容
函数名:int DoHTML(FILE *f, char *name)
发送纯文本(TXT)文件内容
函数名:int DoText(FILE *f, char *name)
发送Jpeg图像文件内容
函数名:int DoJpeg(FILE *f, char *name)
发送GIF图像文件内容
函数名:int DoGif(FILE *f, char *name)null/***************头文件****************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "pthread.h"
简单web服务器的源程序httpd.cnullint KEY_QUIT=0;
int TIMEOUT=30; //定义超时时间为30秒
#ifndef O_BINARY
#define O_BINARY 0
#endif
char referrer[128];
int content_length;
#define SERVER_PORT 80 //使用端口80
nullint PrintHeader(FILE *f, int content_type)
{ //发送HTTP文件头函数
alarm(TIMEOUT); //超时报警处理
fprintf(f,"HTTP/1.0 200 OK\n");
switch (content_type)
{ //选定的文件的类型信息
case 't':
fprintf(f,"Content-type: text/plain\n");
break;
case 'g':
fprintf(f,"Content-type: image/gif\n");
break;
case 'j':
fprintf(f,"Content-type: image/jpeg\n");
break;
case 'h':
fprintf(f,"Content-type: text/html\n");
break;
}
fprintf(f,"Server: uClinux-httpd 0.2.2\n");
fprintf(f,"Expires: 0\n");
fprintf(f,"\n");
alarm(0);//停止超时报警
return(0);
}nullint DoJpeg(FILE *f, char *name)
{ //发送JPEG文件函数
char *buf;
FILE * infile;
int count;
if (!(infile = fopen(name, "r"))) {
alarm(TIMEOUT); //超时报警处理
fprintf(stderr, "Unable to open JPEG file %s, %d\n", name,
errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,‘j’); //发送JPEG类HTTP协议数据头
copy(infile,f); //发送JPEG文件
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}nullint DoGif(FILE *f, char *name)
{ //发送GIF文件函数
char *buf;
FILE * infile;
int count;
if (!(infile = fopen(name, "r"))) {
alarm(TIMEOUT);
fprintf(stderr, "Unable to open GIF file %s, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'g');//发送GIF类HTTP协议数据头
copy(infile,f); //发送输出GIF文件
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}null/**********输出目录数据,如果超时则退出程序*********/
int DoDir(FILE *f, char *name)
{
char *buf;
DIR * dir;
struct dirent * dirent;
if ((dir = opendir(name))== 0) {
fprintf(stderr, "Unable to open directory %s, %d\n", name, errno);
fflush(f);
return -1;
}
PrintHeader(f,'h');
alarm(TIMEOUT);
fprintf(f, "Index of %s
\n\n",name);
alarm(0);
nullif (name[strlen(name)-1] != '/') {
strcat(name, "/");
}
while(dirent = readdir(dir)) {
alarm(TIMEOUT);
fprintf(f, "%s
\n", name, dirent->d_name, dirent->d_name);
alarm(0);
}
closedir(dir);
return 0;
}nullint DoHTML(FILE *f, char *name)
{ //发送HTML网页函数
char *buf;
FILE *infile;
int count;
char * dir = 0;
if (!(infile = fopen(name,"r"))) {
alarm(TIMEOUT);
fprintf(stderr, "Unable to open HTML file %s, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'h'); //发送HTML类HTTP协议数据头
copy(infile,f); //输出网页
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}nullint DoText(FILE *f, char *name)
{//发送文本文件函数
char *buf;
FILE *infile;
int count;
if (!(infile = fopen(name,"r"))) {
alarm(TIMEOUT);
fprintf(stderr, "Unable to open text file %s, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,‘t’); //发送文本类HTTP协议数据头
copy(infile,f); //发送文本文件
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}nullint ParseReq(FILE *f, char *r)
{ //解析HTTP请求函数
char *bp;
struct stat stbuf;
char * arg;
char * c;
int e;
int raw;
while(*(++r) != ' ');
while(isspace(*r))
r++;
while (*r == '/')
r++;
bp = r;
while(*r && (*(r) != ' ') && (*(r) != '?'))
r++; nullif (*r == '?')
{
char * e;
*r = 0;
arg = r+1;
if (e = strchr(arg,' '))
{
*e = '\0';
}
} else
{
arg = 0;
*r = 0;
}
c = bp;
if (c[0] == 0x20){
c[0]='.';
c[1]='\0';
}
if(c[0] == '\0') strcat(c,".");
nullif (c && !stat(c, &stbuf))
{
if (S_ISDIR(stbuf.st_mode))
{
char * end = c + strlen(c);
strcat(c, "/index.html");
if (!stat(c, &stbuf))
{
DoHTML(f, c); //HTML文件处理
}
else
{
*end = '\0';
DoDir(f,c); //目录文件处理
}
}
nullvoid sigalrm(int signo) //信号报警退出函数
{
exit(0);
}
int HandleConnect(int fd) //连接处理函数
{
FILE *f;
char buf[160];
char buf1[160];
f = fdopen(fd,"a+");
if (!f) {
fprintf(stderr, "httpd: Unable to open httpd input fd, error %d\n", errno);
alarm(TIMEOUT);
close(fd);
alarm(0);
return 0;
}nullsetbuf(f, 0);
alarm(TIMEOUT);
if (!fgets(buf, 150, f)) { //读连接,如出错提示
fprintf(stderr, "httpd: Error reading connection, error %d\n", errno);
fclose(f);
alarm(0);
return 0;
}
alarm(0);
referrer[0] = '\0';
content_length = -1;
alarm(TIMEOUT);
nullelse if (!strcmp(r - 4, ".gif"))
DoGif(f,c);// gif文件处理
else if (!strcmp(r - 4, ".jpg") || !strcmp(r - 5, ".jpeg"))
DoJpeg(f,c);
else if (!strcmp(r - 4, ".htm") || !strcmp(r - 5, ".html"))
DoHTML(f,c); //HTML文件处理
else
DoText(f,c); //文本文件处理
}
else{
PrintHeader(f,‘h’);//发协议文件头
alarm(TIMEOUT);
fprintf(f, "404 File Not Found\n");
fprintf(f, "The requested URL was not found on this server\n");
alarm(0);
}
return 0;
}null
//读下一行进行解析
while (fgets(buf1, 150, f) && (strlen(buf1) > 2)) {
alarm(TIMEOUT);
if (!strncasecmp(buf1, "Referer:", 8)) {
char * c = buf1+8;
while (isspace(*c))
c++;
strcpy(referrer, c);
}
else if (!strncasecmp(buf1, "Referrer:", 9)) {
char * c = buf1+9;
while (isspace(*c))
c++;
strcpy(referrer, c);
}
else if (!strncasecmp(buf1, "Content-length:", 15)) {
content_length = atoi(buf1+15);
}
}
alarm(0);nullif (ferror(f)) {
fprintf(stderr, "http: Error continuing reading connection, error %d\n", errno);
fclose(f);
return 0;
}
ParseReq(f, buf); //解析HTTP请求并输出
alarm(TIMEOUT);
fflush(f);
fclose(f);
alarm(0);
return 1;
}nullvoid* key(void* data) //键盘处理函数
{
int c;
for(;;){
c=getchar();
if(c == 'q' || c == 'Q'){
KEY_QUIT=1;
exit(10);
break;
}
}
}
nullint main(int argc, char *argv[]) //主函数定义
{
int fd, s;
int len;
volatile int true = 1;
struct sockaddr_in ec;
struct sockaddr_in server_sockaddr;
pthread_t th_key; //声明了一个线程
void * retval;
//获取异常信号定义
signal(SIGCHLD, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, sigalrm);
chroot(HTTPD_DOCUMENT_ROOT);//设置工作根目录
printf("starting httpd...\n");
printf("press q to quit.\n");nullif (argc > 1 && !strcmp(argv[1], "-i")) {
//从inted服务器启动,处理来自标准输入的连接
fclose(stderr);
HandleConnect(0);
exit(0);
}
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {//创建套接字创建,不成功提示并退出
perror("Unable to obtain network");
exit(1);
}
if((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&true,
sizeof(true))) == -1) {//设置套接字参数,不成功提示并退出
perror("setsockopt failed");
exit(1);
}null //添服务器的数据结构
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(SERVER_PORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (struct sockaddr *)&server_sockaddr,
sizeof(server_sockaddr)) == -1) {//进行绑定,不成功提示并退出
perror("Unable to bind socket");
exit(1);
}
if(listen(s, 8*3) == -1) { //监听请求
perror("Unable to listen");
exit(4);
}
nullpthread_create(&th_key, NULL, key, 0);//创建键盘处理线程
printf("wait for connection.\n");
while (1) {
len = sizeof(ec);
if((fd = accept(s, (void *)&ec, &len)) == -1) {//接收连接
exit(5);
close(s);
}
HandleConnect(fd); //连接处理
}
pthread_join(th_key, &retval);
}
本文档为【WEB服务器】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。