webserver实现
最近的工作需求client和server使用https协议进行通讯,我负责client编写程序,在操作系统的-depth理解认为一旦前webserver实现,整理代码:
#include"apue.h" extern char **environ;
void clienterror(int fd,char *cause,char *errnum,char *shortmsg,char *longmsg)
{
char buf[MAXLINE],body[MAXLINE];
sprintf(body,"<html><title>Tiny Error</title>");
sprintf(body,"%s<body bgcolor=""ffffff"">\r\n",body);
sprintf(body,"%s%s:%s\r\n",body,errnum,shortmsg);
sprintf(body,"%s<p>%s:%s\r\n",body,longmsg,cause);
sprintf(body,"%s<hr><em>The tiny Web server</em?\r\n",body); sprintf(buf,"HTTP/1.0 %s %s\r\n",errnum,shortmsg);
rio_writen(fd,buf,strlen(buf));
sprintf(buf,"Content-type:text/html\r\n");
rio_writen(fd,buf,strlen(buf));
sprintf(buf,"Content-length:%d\r\n\r\n",(int)strlen(body));
rio_writen(fd,buf,strlen(buf));
rio_writen(fd,body,strlen(body));
} void read_requesthdrs(rio_t *rp)
{ char buf[MAXLINE];
rio_readlineb(rp,buf,MAXLINE);
while(strcmp(buf,"\r\n"))
{
rio_readlineb(rp,buf,MAXLINE);
printf("%s",buf);
}
return;
} int parse_uri(char *uri,char *filename,char *cgiargs)
{
char *ptr;
printf("parse_uri(uri):%s\n",uri);
if(!strstr(uri,"cgi-bin"))
{
strcpy(cgiargs,"");
strcpy(filename,".");
strcat(filename,uri);
if(uri[strlen(uri)-1]=='/')
strcat(filename,"home.html");
return 1;
} else
{
ptr=index(uri,'?');
if(ptr)
{
strcpy(cgiargs,ptr+1);
*ptr='\0';
}
else
strcpy(cgiargs,"");
strcpy(filename,".");
strcat(filename,uri);
return 0; }
} void get_filetype(char *filename,char *filetype)
{ if(strstr(filename,".html"))
strcpy(filetype,"text/html");
else if(strstr(filename,".gif"))
strcpy(filetype,"image/gif");
else if(strstr(filename,".jpg"))
strcpy(filetype,"image/jpeg");
else
strcpy(filetype,"text/plain");
} void serve_dynamic(int fd,char *filename,char *caiargs)
{
char buf[MAXLINE],*emptylist[]={NULL}; sprintf(buf,"HTTP/1.0 200 OK\r\n");
rio_writen(fd,buf,strlen(buf));
sprintf(buf,"Server:Tiny Web Server\r\n");
rio_writen(fd,buf,strlen(buf)); if(fork()==0)
{
setenv("QUERY_STRING",caiargs,1);
dup2(fd,STDOUT_FILENO);
execve(filename,emptylist,environ);
}
wait(NULL);
} void serve_static(int fd,char *filename,int filesize)
{ int srcfd;
char *srcp,filetype[MAXLINE],buf[MAXLINE]; get_filetype(filename,filetype);
sprintf(buf,"HTTP/1.0 200 OK\r\n");
sprintf(buf,"%sServer:Tiny Web Server\r\n",buf);
sprintf(buf,"%sContent-length:%d\r\n",buf,filesize);
sprintf(buf,"%sContent-type:%s\r\n\r\n",buf,filetype);
rio_writen(fd,buf,strlen(buf)); srcfd=open(filename,O_RDONLY,0);
srcp=mmap(0,filesize,PROT_READ,MAP_PRIVATE,srcfd,0);
close(srcfd);
rio_writen(fd,srcp,filesize);
munmap(srcp,filesize);
} void doit(int fd)
{
int is_static;
struct stat sbuf;
char buf[MAXLINE],method[MAXLINE],uri[MAXLINE],version[MAXLINE];
char filename[MAXLINE],cgiargs[MAXLINE];
rio_t rio; rio_readinitb(&rio,fd);
rio_readlineb(&rio,buf,MAXLINE);
sscanf(buf,"%s %s %s",method,uri,version);
if(strcasecmp(method,"GET"))
{
clienterror(fd,method,"501","Not implemented","Tiny does not implemented this method");
return;
} read_requesthdrs(&rio); is_static=parse_uri(uri,filename,cgiargs);
if(stat(filename,&sbuf)<0)
{
clienterror(fd,filename,"404","Not found","Tiny couldn't find this file");
return;
} if(is_static)
{
if(!(S_ISREG(sbuf.st_mode))||!(S_IRUSR&sbuf.st_mode))
{
clienterror(fd,filename,"403","Forbidden","Tiny could't read the file");
return;
}
serve_static(fd,filename,sbuf.st_size);
}
else
{
if(!(S_ISREG(sbuf.st_mode))|!(S_IXUSR&sbuf.st_mode))
{
clienterror(fd,filename,"403","Forbidden","Tiny could't run the CGI program");
return;
}
serve_dynamic(fd,filename,cgiargs);
} } int main(int argc,char **argv)
{
int listenfd,connfd,port,clientlen;
struct sockaddr_in clientaddr; if(argc!=2)
{
fprintf(stderr,"usage:%s <port> \n",argv[0]);
exit(0);
} port=atoi(argv[1]); listenfd=open_listenfd(port);
while(1)
{
clientlen=sizeof(clientaddr);
connfd=accept(listenfd,(SA*)&clientaddr,&clientlen);
doit(connfd);
close(connfd);
}
}
我们能够直接使用浏览器測试上面的程序。比方当前server程序的文件夹以下有一个index.html,仅仅要我们在浏览器中输入:
localhost:<port>/index.html就能够请求到index.html
server端收到的浏览器请求行例如以下:
版权声明:本文博客原创文章,博客,未经同意,不得转载。
webserver实现的更多相关文章
- WebServer+ADO+百万数据查询
很简单的demo,查询速度快,易理解,废话不说 上demo 看完就明白了 源码地址:http://files.cnblogs.com/files/SpadeA/WebDemo.zip 这是关于Web ...
- webserver[实时查询当天的天气情况]
1.webserver是什么? 日常生活中经常会使用到webserver,注册时,会收到验证码,购买东西时,会收到短信,假如,A公司网站和B公司合作,那么A公司注册对的用户可以直接推送给B网站,那怎么 ...
- Warning: file_put_contents(data.txt): failed to open stream: Permission denied in /Library/WebServer/Documents/test.php on line 22
最近在学习PHP 在保存文件的时候报Warning: file_put_contents(data.txt): failed to open stream: Permission denied in ...
- [C#] 图文解说调用WebServer实例
本文旨在实现如何在.NET环境下调用WebServer,以天气接口为例进行说明. WebServer地址:http://www.webxml.com.cn/WebServices/WeatherWeb ...
- python开启简单webserver
python开启简单webserver linux下面使用 python -m SimpleHTTPServer 8000 windows下面使用上面的命令会报错,Python.Exe: No Mod ...
- C# 如何调用WebServer函数
WebServer(ASMX)服务程序网站的编写简单总结. WebServer中遇到的问题 编写WebServer程序VS运行调试时如果出现 System.Data.OracleClient.Orac ...
- [Top-Down Approach] Assignment 1: WebServer [Python]
Today I complete Socket Programming Assignment 1 Web Server Here is the code: #!/usr/bin/python2.7 # ...
- 【监控】WebServer入库与缓存更新代码优化小计
问题描述: 通过WebServer将监控数据入库到Hbase,在入库之前需要将指标与ip的列表更新到缓存中,以便前台页面随时选择查看.前两天上了一些新用户导致负载增加,逐渐发现某些用户的监控场景出现丢 ...
- Linux WebServer WebRoot Path Identification
目录 . HTTPD(Apache) . NGINX . TENGINE . JBOSS . TOMCAT . LIGHTTPD 1. HTTPD(Apache) 0x1: 启动参数 Usage: . ...
- iOS - Apache Tomcat WebServer 服务器配置
前言 提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提前准备好的软件: apache-tomcat-6.0.45.tar.gz eclip ...
随机推荐
- xamarin之 安装工具介绍
原文:xamarin之 安装工具介绍 思考: 1, 一定要按照顺序安装吗? 先装JDK,再装Android SDK 原因:Android SDK采用了Java语言 先装Android SDK,再装A ...
- 工作经常使用的SQL整理,实战篇(三)
原文:工作经常使用的SQL整理,实战篇(三) 工作经常使用的SQL整理,实战篇,地址一览: 工作经常使用的SQL整理,实战篇(一) 工作经常使用的SQL整理,实战篇(二) 工作经常使用的SQL整理,实 ...
- [置顶] 利用CXF发布webService的小demo
其实webService的发布不仅仅只有xfire,今天,给大家介绍一下用CXF发布一个webService的小demo,CXF也是我做webService用的第一个框架... 先将相关的jar引进来 ...
- Test SRM Level Two: CountExpressions, Brute Force
题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=8157 这道题目跟扑克牌算24的题目比较像,但要简单一些.点击查 ...
- HDU 2063 过山车 二分图题解
一个男女搭配的关系图,看能够凑成多少对,基本和最原始的一个二分图谜题一样了,就是 一个岛上能够凑成多少对夫妻的问题. 所以是典型的二分图问题. 使用匈牙利算法,写成两个函数,就很清晰了. 本程序还带分 ...
- logback与Spring、SpringMVC结合使用教程(转) logback good
摘要:本文主要介绍了如何在spring.springMVC中使用logback 一.logback与Spirng结合使用 1.maven添加引用: <dependency> <gro ...
- 【白痴弟弟和你加强应用层】阅读 Develop API Guides 思考(一个)
转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 动态检測设备属性 关于targetSdkVersion的含义 关于onSaveInstanceState的高 ...
- 在C#环境中动态调用IronPython脚本(一)
本文讲述用C#调用Ironpython运行环境,解析并运行动态pyhton脚本.这种情况应用在那些需要滞后规定行为的场合,例如,动态计算项(计算引擎),用户可以自定义计算内容.计算公式等. 本文的代码 ...
- nginx lua redis 访问频率限制(转)
1. 需求分析 Nginx来处理访问控制的方法有多种,实现的效果也有多种,访问IP段,访问内容限制,访问频率限制等. 用Nginx+Lua+Redis来做访问限制主要是考虑到高并发环境下快速访问控制的 ...
- JDK5什么是新的线程锁技术(两)
一个. Lock线程同步实现互斥 Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也是一个对象. 两个线程运行的代码片段要实现同步相互排斥的效果.他们必须用 ...