一个Web Server就是个服务器软件(程序),或者是运行这个服务器软件的硬件(计算机),其主要功能是通过HTTP协议与客户端进行通信,来接收,存储,处理来自客户端的HTTP请求,并对其做出HTTP响应,返回给客户端其请求的内容或返回一个error信息。
通常用户使用Web浏览器与相应的服务器进行通信, 在浏览器中输入“域名”或“ip地址:端口号”,浏览器则先将你的域名解析成相应的ip地址或者直接根据你的ip地址向对应的Web服务器发送一个HTTP请求,这个过程首先要通过TCP协议的三次握手建立与目标Web服务器的连接,然后HTTP协议生成针对目标Web服务器的HTTP请求报文,通过TCP,IP等协议发送到目标服务器上。
HTTP协议(应用层协议)
简介
超文本传输协议,是一个简单的请求,响应协议,它通常运行在TCP之上,它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应,请求和响应消息的头以ASCII形式给出,而消息内容则具有一个类似MMF的格式,HTTP是万维网的数据通信的基础。
工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端,HTTP协议采用了请求/响应模型,客户端向服务器发送一个请求报文,请求报文包含请求的方法,URL,协议版本,请求头部和请求数据,服务器以一个状态行作为响应,响应的内容包括协议的版本,成功或错误代码,服务器信息,响应头部和响应数据。
以下是HTTP请求/响应的不步骤:
1.客户端连接到Web服务器
2.发送HTTP请求
3.服务器接收请求并返回HTTP响应
4.释放连接TCP连接
5.客户端浏览器解析HTML内容
例如L在浏览器地址输入URL,按下回车会经历以下步骤:
1.浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址;
2.解析出IP地址后,根据该IP地址和默认端口80,和服务器建立TCP连接;
3.浏览器发出读取文件,(URL中域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器;
4.服务器对浏览器请求作出响应,并把对应HTTP文本发生给浏览器;
5.释放TCP连接;
6.浏览器将该HTTP文本显示内容。
客户端的选择有:浏览器,curl命令,Postman。
HTTP是一种无状态的协议。
请求报文格式
响应报文格式
请求报文中,第一行是起始行,下面的是首部字段,然后是两个空行,换行是\r\n,连续的两个\r\n代表首部字段结束了。
HTTP请求方法
HTTP/1.1协议中共定义了八种方法来以不同的方式来操作指定的资源:
1.GET:向指定的资源发出“显示”请求,使用GET方法应该只用在读取数据,而不应该被用于产生”副作用“的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。
2.HEAD:与GET方法一样,都是向服务器发出指定资源额请求,只不过服务器将不传回资源的文本部分,它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中”关于该资源的信息“
3.POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件),数据被包含在请求报文中,这个请求可能会创建新的资源或修改现有资源,或二者皆有。
4.PUT:向指定资源上传最新内容。
5.DELETE:请求服务器删除Request-URL所标识的作用。
6.TRAC:回显服务器收到的请求,主要用于测试或诊断。
7.OPTIONS:这个方法可使服务器传回该资源所支持的所有HTTP请求方法。
8.CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器,通常用于SSL加密服务器的连接。
一般情况下GET,POST方法是最常用的。这里并不完全,要了解更多方法,查看RFC文档或者MDN文档。
boundary用来分割不同键值对。
前面使用的是&作为分隔符,用一长串的数字来分割,如果出现和数据相同,则提示重新请求。
浏览器上怎么发POST请求????
先做一个网页出来,和网页里面的内容进行交互。
1.x-www-form-urlencoded key1=value1&key2=value2 短数据,类似登陆注册
2.form-data 指定一个boundary来分割, 可以用来上传文件
uri的路径和path部分
url的路径总是以/开头的,以?结尾,没写的话,默认是/。
怎么样解析path和query?
path由服务端自己决定,比如www.baidu.com/s?就是百度的搜索服务。一般用来对应资源(1.文件,2.某个函数或者服务)。
HTPP版本
起始行的第三个字段是http的版本,它有/0.9 /1.0 /1.1 /2.0 /3.0
我们要关注的是1.1版本,这是使用最多的版本,它支持持久连接,简而言之就是长连接。心跳,根据最后一次请求数据的时间,来依次断连。http是一次请求一次响应,适合短连接。两端的数据都不变,即客户端的ip和port,服务器的ip和port都不变。
状态码和状态字符串
200 OK 表示成功
301 Moved Permanently 表示永久重定向
302 Found 临时重定向
400 Bad Request 有错误,不告诉客户端错在哪
403 Forbidden 服务器有能力处理该请求,但是拒绝授权访问
404 Not Found 客户端有误,服务器端无法找到所请求的资源
500 Internal Server Error 万能响应代码
502 Bad Gateway 网关错误
#include "linuxHeader.h"
#include <memory>
#include <string>
class HttpServer
{
public:
HttpServer(const char *ip, const char *port)
: _ip(ip), _port(port)
{
}
void start()
{
_socketfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(_ip);
addr.sin_port = htons(atoi(_port));
int reuse = 1;
setsockopt(_socketfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
bind(_socketfd, (struct sockaddr *)&addr, sizeof(addr));
listen(_socketfd, 10);
}
void RecvAndShow()
{
// 连接客户端
int netFd = accept(_socketfd, NULL, NULL);
// 使用RAII管理缓冲区
std::unique_ptr<char[]> buf(new char[4096]);
bzero(buf.get(), 4096);
// 读取请求的内容,直接显示在stderr中
recv(netFd, buf.get(), 4096, 0);
fprintf(stderr, "%s\n", buf.get());
// http协议头
std::string firstLine = "HTTP/1.1 302 Moved Temporarily\r\n";
send(netFd, firstLine.c_str(), firstLine.size(), 0);
std::string headers = "Content-Type:text/plain\r\n"
"Location:https:/www.taobao.com\r\n"
"Content-Length:5\r\n";
send(netFd, headers.c_str(), headers.size(), 0);
std::string emptyLine = "\r\n";
send(netFd, emptyLine.c_str(), emptyLine.size(), 0);
// http协议数据
std::string body = "hello";
send(netFd, body.c_str(), body.size(), 0);
close(netFd);
fprintf(stderr, "connection closed\n");
}
private:
const char *_ip;
const char *_port;
int _socketfd;
};
RESTful设计风格
REST全称是表述性状态转移,那究竟指的是什么的表述? 其实指的就是资源。任何事物,只要有被引用到的必要,它就是一个资源。资源可以是实体(例如手机号码),也可以只是一个抽象概念(例如价值) 。下面是一些资源的例子:
-
某用户的手机号码
-
某用户的个人信息
-
最多用户订购的GPRS套餐
-
两个产品之间的依赖关系
-
某用户可以办理的优惠套餐
-
某手机号码的潜在价值
要让一个资源可以被识别,需要有个唯一标识,在Web中这个唯一标识就是URI(Uniform Resource Identifier)。
URI既可以看成是资源的地址,也可以看成是资源的名称。如果某些信息没有使用URI来表示,那它就不能算是一个资源, 只能算是资源的一些信息而已。URI的设计应该遵循可寻址性原则,具有自描述性,需要在形式上给人以直觉上的关联。
如果用户的接口设计符合REST风格,就称作是RESTful的接口设计,REST风格的特点如下:
使用HTTP方法表示行为: GET PUT POST DELETE分别表述查改增删;
所有的对象都抽象成资源,每一个资源都使用URL的路径来标识;
所有传递的参数都放在请求和响应的报文体中;
使用json或者是xml编码数据;
客户端不再得到完整的html,数据的展示效果由客户端完成
怎么样设计一个restful的接口????
1.方法里面放行为:增删查改,2.资源在url的path,3.将参数放在请求体里面,用JSON/XML组织,4.得到的响应体只有关键信息。把视图和关键状态分离。
好处:幂等性
HTTPS的实现原理
http明文传递,风险:信息泄漏,是不安全的。
使用密文传递,传递到服务器之后进行解密。
http+ssl 将传递到网络上的数据进行加密。
对称加密
客户端由原始文档,密钥(只有一份)合成生成一份密文,通过网络传递到服务器,通过密钥和密文解密得到原始文档。同一个密钥可以做加密操作也可以做解密操作,AES/DES。
优点:效率比较高
非对称加密
有一对互补的钥匙,一个公钥,一个私钥,客户端生成了一对公钥和私钥,还有一个原始文档,它把原始文档通过私钥进行加密,得到一份密文,然后把密文和公钥通过网络发给服务器,服务器可以使用公钥和密文进行解密得到密文。
用处:身份验证,客户端有一对公钥和私钥,把公钥给服务器,登录的时候提供私钥,两个是互补的,不需要密码就可以登录。
一般是RSA系列算法。
优点:更加安全
怎么实现HTTPS?
两个阶段:
握手阶段,使用非对称加密将对称加密的密钥传输过去。
传输阶段,使用对称加密进行传输数据。