web服务器实现

最近工作中需要客户端和服务器使用https协议进行通信,我负责客户端程序的编写,想到以前在深入理解操作系统中看过web服务器的实现,代码整理如:

#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);
    }
}

我们可以直接使用浏览器测试上面的程序,比如当前服务器程序的目录下面有一个index.html,只要我们在浏览器中输入:

localhost:<port>/index.html就可以请求到index.html

服务器端收到的浏览器请求行如下:

web服务器实现,布布扣,bubuko.com

时间: 2024-10-21 01:30:53

web服务器实现的相关文章

pfsense Web服务器负载平衡配置示例

在pfsense的网关和服务器中有两种类型的负载平衡功能.网关负载平衡可以通过多个WAN连接分发Internet绑定的流量.服务器负载平衡管理传入流量,因此它利用多个内部服务器进行负载分配和冗余,服务器负载平衡允许流量在多个内部服务器之间分配,它最常用于Web服务器和SMTP服务器.下面我们就以实例来介绍服务器负载平衡的设置. 下面介绍如何通过pfsense2.32配置Web服务器的负载平衡. 网络环境 服务器负载平衡示例网络环境 上图为示例网络环境.它由单个防火墙组成,使用其WAN IP地址池

VS2013 VS2015 VS2017调试出现无法启动iis express web服务器

最近老是遇到这个问题,天天如此,烦死人,网上答案繁多,但是都解决不了,也是由于各种环境不同导致的,这里把几种解决方法都记录下 一.其他项目都可以,就这么一个不行 因为其他项目都可以,就这么一个不行,所以基本就是配置问题,网上的办法都试了,我试了都没用,现在说说我的解决办法 用记事本或者其他什么文本编辑器,打开项目的.csproj文件,定位到<WebProjectProperties>,把关于IIS的配置<DevelopmentServerPort>.<DevelopmentS

linux学习笔记——搭建基于nginx的web服务器、多核配置、nginx配置参数

############ 认识nginx #############Nginx:(发音同 engine x)是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,最初供俄国大型的入口网站及搜寻引擎Rambler(俄文:Рамблер)使用.  其优点是轻量级(占有内存少),高并发(并发能力强),事实上nginx的并发能力确实在同类型的网页伺服器中表现较好.目前中国大陆使用ngi

使用TMG2010让多个web服务器共用一个公网地址

背景描述: 公司原有2个Web服务器托管在ISP中心,其中一个Web服务器上有3个网站,另外一个有2个网站.每1个Web服务器都有1个公网IP,由于负荷较轻,从节约成本出发,使用VMware将5台服务器整合在一台物理服务器上,此时就产生了一个问题,怎么让这5个分布在2台虚拟服务器上不同域名的网站共用公网地址的80端口? 操作步骤: 1.在VMware上虚拟出一台服务器,安装TMG2010,此时的网络拓扑结构为: 2.分别按照原来的结构在Web服务器上部署相关网站 3.在TMG上创建1个Web侦听

WEB服务器与应用服务器

Web服务器(Web Server) 通俗的讲,Web服务器的基本功能就是提供Web信息浏览服务.它只需支持HTTP协议.HTML文档格式及URL.与客户端的网络浏览器配合.因为Web服务器主 要支持的协议就是HTTP,所以通常情况下HTTP服务器和WEB服务器是相等的. 以这样的定义,IIS.Apache.Tomcat都可以属于Web服务器. [转载使用,请注明出处:http://blog.csdn.net/mahoking] Web服务器(Web Server)可以解析(handles)HT

EG:nginx反向代理两台web服务器,实现负载均衡 所有的web服务共享一台nfs的存储

step1: 三台web服务器环境配置:iptables -F; setenforce 0 关闭防火墙:关闭setlinux step2:三台web服务器 装软件 step3:主机修改配置文件:vim /usr/local/nginx/conf/nginx.conf 代理服务器修改文件:修改端口即可,端口可以自己设 ,不改默认的也行,但是得相应匹配 为测试需要,更改三台机器nginx的html文件: mv /usr/local/nginx/html/index.html /usr/local/n

Nginx配置文件(作为Web服务器)

Nginx作为Web服务器时,其配置文件参数如下: #user  nobody; #默认的运行用户 worker_processes  1; #工作进程数,建议和CPU核心数一致,默认为1 #error_log  logs/error.log; #error_log  logs/error.log  notice; #error_log  logs/error.log  info; #pid        logs/nginx.pid; events { worker_connections  

简介web服务器的工作原理

一 什么是web服务器,应用服务器和web容器? 对于web服务器与应用服务器:"在过去它们是有区别的,但是这两个不同的分类慢慢地合并了,而如今在大多在情况下和使用中可以把它们看成一个整体." 但是当有人说到"web服务器"时,你通常要把它认为是以HTTP为核心.web UI为向导的应用. 当有人说到"应用服务器"时,你需要想到"高负载.企业级特性.事务和队列.多通道通信(HTTP和更多的协议)". 在Java方面,web容器

WEB服务器与应用服务器解疑

1.WEB服务器: 理解WEB服务器,首先你要理解什么是WEB?WEB你可以简单理解为你所看到的HTML页面就是WEB的数据元素,处理这些数据元素的应用软件就叫WEB服务器,如IIS.apache. WEB服务器与客户端打交道,它要处理的主要信息有:session.request.response.HTML.JS.CS等. 2.应用服务器: 应用服务器如JSP,处理的是非常规性WEB页面(JSP文件),他动态生成WEB页面,生成的WEB页面在发送给客户端(实际上当应用服务器处理完一个JSP请求并

python 启动简单web服务器

有时我们在开发web静态页面时,需要一个web服务器来测试. 这时可以利用python提供的web服务器来实现. 1.在命令行下进入某个目录 2.在该目录下运行命令: python -m SimpleHTTPServer 3.在浏览器打开 http://localhost:8000/路径 这里的路径是相对上面当前目录下的路径.