Web版简易加法计算

##HTTP
HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。(我们称这个客户端)叫用户代理。应答的服务器上存储着(一些)资源,比如HTML文件和图像。(我们称)这个应答服务器为源服务器。

通常,由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端发送过来的请求。一旦收到请求,服务器(向客户端)发回一个状态行,比如"HTTP/1.1 200 OK",和(响应的)消息,消息的消息体可能是请求的文件、错误消息、或者其它一些信息。HTTP使用TCP而不是UDP的原因在于(打开)一个网页必须传送很多数据,而TCP协议提供传输控制,按顺序组织数据,和错误纠正。

######HTTP服务器
通过浏览器,发送一个标准的HTTP请求,就能够得到一个标准的HTTP响应
项目中实现的是:通用的HTTP服务器框架来实现自己的业务

要实现的核心功能(需求分析(粗略))
  1. 能够接受标准的HTTP请求
  2. a)GET方法
  3. b)POST方法
  4. 能够根据请求作出响应一个标准的HTTP响应
  5. a)能够根据url返回一个服务器上的静态文件(html,css,JavaScript,图片等)
  6. b)根据请求中的参数(GET url,POST body)动态生成一个页面(//这个页面是基于CGI的方法,CGI可以理解成一个标准)
模块划分
  1. 初始化模块 //实现一个TCP服务器
  2. 响应请求模块 //使用多线程的方式处理并发的请求
    a)读取请求并解析 //操作和解析字符串(反序列化)
    b)根据请求内容进行计算
    i)处理静态文件 //直接将静态文件的内容返回
    ii)处理动态页面 //使用CGI的方式实现动态计算生成页面
    c)把响应的结果写回给客户端 //操作和拼接字符串

请求报文的构成:
这里写图片描述

响应报文的构成
这里写图片描述

#####告知服务器意图的HTTP方法
GET方法(获取资源)
用来请求访问已被URI识别的资源。指定的资源经服务器端解析后返回响应内容。
使用GET方法的请求·响应的例子
这里写图片描述
POST方法(传输实体主体)
POST的主要目的并不是获取响应的主体内容。
使用POST方法的请求·响应的例子
这里写图片描述

######返回结果的HTTP状态码
状态码类别

状态码 类别 原因短语
1XX Information(信息性状态码) 接收的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错

//数字中的第一位指定了响应类别,后两位无分类

常用状态码:
200 OK 请求被正常处理
204 No Content 请求已成功处理,但响应报文中不含实体的主体部分
206 Partial Content 范围性请求且服务器成功执行
301 Moved Permanently 永久性重定向
302 Found 临时性重定向
303 See Other 使用GET方法定向获取请求资源
304 Not Modified 请求未满足
307 Temporary Redirect 临时重定向
400 Bad Request 请求报文中存在语法错误
401 Unauthorized 发送的请求需要有通过HTTP认证(BASIC认证、DIGEST认证)的认证信息
403 Forbidden 对请求资源的访问被服务器拒绝了
404 Not Found 服务器上无法找到请求的资源
500 Internal Server Error 服务器端在执行请求时发生了错误
503 Service Unavailable 服务器暂时处于超负载或正在进行停机维护,现在无法处理请求

#####CGI协议
CGI是外部应用程序(CGI程序)与WEB服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的过程。CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。

1.收到的请求是一个(GET && 带有query_string )|| (POST) 触发CGI逻辑
2.创建一个子进程,子进程通过exec执行一个本地的可执行程序,通过这个可执行程序完成动态页面的计算
3.这里涉及到一个重要的问题:

  1. 子进程需要知道http请求具体长什么样子;
    需要知道进行替换哪个可执行文件
    需要知道HTTP请求的方法是什么 (环境变量METHOD )
    需要知道query_string是什么 (环境变量 QUERT_STRING )
    需要知道body是什么 (匿名管道)

  2. 子进程也要把计算完毕的结果反馈给父进程
    http响应的body ( 匿名管道 )
    部分header ( 匿名管道 ) (子进程把标准输入和标准输出重定向到管道上)

例如:1+2
收到的http请求可能是GET请求,query_string包含了1+2,也可能是一个POST请求,body中包含了1+2

子进程程序替换之后,CGI程序响应数据会这么写:
假设CGI程序返回的html页面是一个
这里写图片描述
以下内容是CGI程序所写回管道的内容(一部分header和一部分body)
这里写图片描述
如果要想仅仅使用管道完成进程间通信的话,要额外的约定协议。
此处的协议指的是,父进程按照啥样的格式组织数据并写入管道,以及子进程按照啥样的格式来解析。
如果以下图这种方式来组织数据的话,则在CGI程序中解析数据会更麻烦些,而如果我们使用环境变量配合管道两个双管齐下的话,子进程直接读取环境变量的内容就能获取方法和content-length,而直接从标准输入中读取数据就能够得到http请求中的body。
这里写图片描述

我在这个HTTP中实现一个简单的CGI程序:
根据请求中的输入数据,计算两个数字的和
两个要相加的数,通过query_string(GET)或者body(POST)来传递
例如:a=100&b=200

代码

http_server.cc

#include "http_server.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sstream>

#include "util.hpp"


typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;

namespace http_server{


int HttpServer::Start(const std::string& ip,short port){
    int listen_sock = socket(AF_INET,SOCK_STREAM,0);
    if(listen_sock <0){
        perror("socket");
        return -1;
    }
    //要给socket加上一个选项,能够重用我们的连接
    int opt = 1;
    setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    addr.sin_port = htons(port);
    int ret = bind(listen_sock,(sockaddr*)&addr, sizeof(addr));
    if(ret < 0){
        perror("bind");
        return -1;
    }
    ret = listen( listen_sock, 5);
    if(ret < 0){
        perror("listen");
        return -1;
    }
   // printf("
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值