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 ...
随机推荐
- uva10465(完全背包,要求装满背包)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&c ...
- Android 自己的自动化测试(2)依据ID查找对象(java)
前一篇文章是写 Android 自己的自动化测试(1)如何安装和卸载应用程序(java) ,以下再探索一下假设在普通java应用程序中,依据ID来查找对象 1.类库依赖: The library de ...
- 点击 下载 pdf
<iframe id="fileDownFrame" src="" style="display:none; visibility:hidde ...
- [Windows Phone] 如何在 Windows Phone 应用程式制作市集搜寻
原文:[Windows Phone] 如何在 Windows Phone 应用程式制作市集搜寻 [说明] 本文说明如何在 Windows Phone 应用程式中,加入市集搜寻的功能,主要使用了 Mar ...
- java Socket的怪异之处
怪异之一: connect(SocketAddress endpoint):这个方法,尝试连接server端,如果连接不上,就抛出IOException异常.如果连接成功了,就继续执行下一步的代码. ...
- sql分隔字符串数组
declare @relation_code nvarchar(1024) set @relation_code = '#10000#10002' set @relation_code=substri ...
- C++类实现最大数的输出
Description 判断整数的大小,输入n个数,找出最大的数并输出. Input 有多组测试实例,输入n,并输入n个数. Output 输出的最大的数,每个输出结果占一行. Sample Inpu ...
- 创建Oracle的用户 create user scott identified by tiger;
在命令行里sqlplus 以system身份登录,password是自己设的system C:\Users\Administrator>sqlplus SQL*Plus: Release 10. ...
- 怎样配置git ssh连接,怎样在GitHub上加入协作开发人员,怎样配置gitignore和怎样在GitHub上删除资源库.
**********1.在运行git push origin master指令时报例如以下错误: iluckysi@ILUCKYSI-PC /d/ilucky/message/code (master ...
- 【数据库摘要】4_Sql_Like
SQL LIKE 操作符 LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式. SQL LIKE 语法 SELECT column_name(s) FROM table_name WHERE ...