概述
HTTP协议
14.1 前言
在TCP/IP协议基础上,有很多应用层协议,支持各种网络应用,比如HTTP,SMTP,FTP等等。HTTP协议是最广泛的应用层协议
14.2 通信模型
-
支持客户/服务器模式。
-
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。
-
灵活:HTTP允许传输任意类型的数据对象。
-
短连接:无连接的含义是限制每次连接只处理一个请求。
-
无状态:HTTP协议是无状态协议。
14.3 地址(URL)
URL全称为Unique Resource Location,用来表示网络资源,可以理解为网络文件路径。URL的格式如下:
例如:
URL的长度有限制,不同的服务器的限制值不太相同,但是不能无限长。以下博文有对RUL长度的一些叙述:
http://www.cnblogs.com/henryhappier/archive/2010/10/09/1846554.html
补充:HTTP协议的服务器和客户端
服务器
Http服务器/Web服务器:apache,nginx,iis(Windows平台)
客户端:浏览器
客户端
curl命令
curl是一个命令行数据传输工具,它支持很多协议,包括DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP。这里使用curl来学习HTTP协议,因此重点说明HTTP相关的内容。
curl命令格式
例如
选项[option]
选项 | 长选项 | 解释 |
---|---|---|
-# | --progress-bar | 显示进度条 |
-d | --data, --data-ascii, --data-binary | post协议的数据 |
-F | --form <name=content> | 提交表单 |
14.4 HTTP请求
HTTP请求由三部分组成,分别是:请求行、消息报头、请求正文
14.4.1 请求方法
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如:GET /index.html HTTP/1.1
。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
而常见的有如下几种:
-
GET
GET方法是HTTP协议中最常见的请求方式,当客户端需要从服务器中读取文档时,往往使用GET方法。GET方法要求服务器URL指定的文档内容。而内容部分,按照HTTP协议规定,放在响应报文的正文部分。
GET方法请求,没有请求正文内容,请求时的参数在URL中携带,由于URL被限制了长度,因此GET方法不适合用于上传数据。同时在浏览器中,通过GET方法来获取网页时,参数会显示在浏览器地址栏上,因此保密性很差。
-
POST
POST方法运行客户端给服务器提供比较多的信息。POST方法将请求参数封装在HTTP请求数据中,而且长度没有限制,因为POST携带的数据,在HTTP的请求正文中。
-
HEAD
HEAD只返回信息头,不要求服务器返回URL所指资源内容。
14.4.2 消息报头
消息报头由关键字/值对组成,每行一对,关键字和值用:分割。
比如
14.4.3 空行
最后一个消息报头和正文之间,是一个空行。GET请求没有正文。
14.4.4 请求正文
请求正文在POST方法中使用。
14.5 HTTP响应
HTTP响应由三部分组成,分别是:状态行、消息报头、响应正文。HTTP响应的格式于请求的格式很类似:
唯一的区别就是第一行的请求行,变成了状态行。状态行格式举例如下:
其中HTTP/1.1表示协议和版本信息,200表示服务器的响应码,OK表示状态码的描述,状态码由3位数组成,第一个数字表示了响应的类别,一共有5种类别。
-
1xx:表示服务器正在处理
-
2xx:成功,请求被正确的理解或者处理
-
3xx:重定向
-
4xx:客户端错误,客户端的请求,服务器无法理解。
-
5xx:服务器错误,服务器未能实现的合法请求。
常见的状态码举例:
-
200 OK:客户端请求成功
-
400 Bad Request:请求报文有语法错误
-
401 Unauthorized:未授权
-
403 Forbidden:服务器拒绝服务
-
404 Not Found:请求的资源不存在
-
500 Internal Server Error:服务器内部错误
-
503 Server Unavailable:服务器临时不能处理客户端请求(稍后可能可以)
响应报文例子:
14.6 使用HTTP协议实现通信
服务器的开发不容易,尤其是开发高性能、稳定性好服务器,更加不容易,因此人们尝试更好简单的方式来开发软件。在服务器方面,使用WEB服务器,采用HTTP协议来代替底层的SOCKET,是常见的选择。采用HTTP协议更加除了能得到稳定的服务器支持外,更加可以兼容各种客户端(手机、PC、浏览器)等等。这样实现了一个服务器之后,多个客户端可以通用。
在开发应用程序时,客户端应用程序为了和WEB服务器通信,需要对请求报文进行打包成HTTP请求格式,而服务器响应了HTTP响应报文到客户端之后,也需要对响应报文进行解释。libcurl库,可以完成这些功能。
而Web服务器的选择是多样化的:Apache,nginx,libevent,tufao。一些使用C/C++开发的开源的Http服务器列表在这里:
http://www.oschina.net/project/tag/106?lang=21&os=0&sort=time
通信时,应用程序的通信报文目前采用的json格式较多,也有一些采用xml格式或者http协议规定的表单格式。
补充
客户端:浏览器
服务器:apache + c语言写的CGI程序
实现HTTP通信
CGI技术在早期解决动态网页,和网页跟服务器交互的问题。
-
apache2安装
-
了解配置
静态文档位置:/var/www/html
apache可执行程序:/usr/lib/cgi-bin/
为了支持CGI,需要以下命令支持
简单的CGI程序代码案例,编译出的可执行程序,需要在/usr/lib/cgi-bin目录下
#include <stdio.h> #include <string.h> #include <stdlib.h> extern char** environ; int main() { // http协议的规定 // 重定向 printf("Content-type:text/htmlnn"); // 输出环境变量 for(int i=0; ;++i) { if(environ[i]) { // printf("%s<br>n", environ[i]); } else { break; } } // 获取环境变量QUERY_STRING的值,获取客户端参数 char* query_string = getenv("QUERY_STRING"); strtok(query_string, "=&"); char* username = strtok(NULL, "=&"); strtok(NULL, "=&"); char* password = strtok(NULL, "=&"); if(strcmp(username, "aa") == 0 && strcmp(password, "bb") == 0) { printf("Login success<br>n"); } else { printf("Login error<br>n"); } }
14.6.1 libcurl
libcurl 官网:https://curl.haxx.se/
libcurl也是curl工具使用的库
-
下载源码
可以到官网下载,更方便的是到github上克隆代码
-
编译和安装
安装完毕之后,头文件
/usr/local/include/curl
/usr/local/lib/libcurl.so
可执行命令
/usr/local/bin/curl
另外一种办法是:可以简单的执行
sudo apt-get install curl
安装curl命令,该命令将curl安装/usr/bin
sudo apt-get install libcurl4-openssl-dev
来安装libcurl,libcurl的安装路径
头文件:/usr/include/curl
库目录:/usr/lib
-
使用
#include <stdio.h> #include <curl/curl.h> bool getUrl(char *filename) { CURL *curl; CURLcode res; FILE *fp; if ((fp = fopen(filename, "w")) == NULL) // 返回结果用文件存储 return false; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Accept: Agent-007"); curl = curl_easy_init(); // 初始化 if (curl) { //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改协议头 curl_easy_setopt(curl, CURLOPT_URL,"http://www.baidu.com"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); //将返回的http头输出到fp指向的文件 curl_easy_setopt(curl, CURLOPT_HEADERDATA, fp); //将返回的html主体数据输出到fp指向的文件 res = curl_easy_perform(curl); // 执行 if (res != 0) { curl_slist_free_all(headers); curl_easy_cleanup(curl); } fclose(fp); return true; } } bool postUrl(char *filename) { CURL *curl; CURLcode res; FILE *fp; if ((fp = fopen(filename, "w")) == NULL) return false; curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookie.txt"); // 指定cookie文件 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "&logintype=uid&u=xieyan&psw=xxx86"); // 指定post内容 //curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080"); curl_easy_setopt(curl, CURLOPT_URL, " http://mail.sina.com.cn/cgi-bin/login.cgi "); // 指定url curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } fclose(fp); return true; } int main(void) { getUrl("/tmp/get.html"); postUrl("/tmp/post.html"); }
基本流程是:
-
初始化CURL环境
-
创建CURL对象
-
设置CURL
-
执行CURL
14.6.2 tufao
tufao是一个由QT编写的HTTP服务器。
tufao代替apache来实现http的通信。
安装tufao
-
获取代码
-
编译和安装
-
sudo apt-get install cmake qtsdk
-
在tufao目录下创建build目录
-
cd build
-
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
-
make
-
sudo make install
-
-
创建工程
-
创建空的工程
-
工程文件中增加
CONFIG += TUFAO1 C++11
-
增加一个类MyServer,一定是QObject派生类
-
增加一个main.cpp实现main函数
-
在MyServer的构造函数,创建Tufao::HttpServer对象server
-
将server的信号
requestReady
和自己写的槽函数slotRequestReady
连接 -
在
slotRequestReady
函数中,实现http协议的响应报文。
-
14.6.3 libevent
略。
14.6.4 json
JSON是一种轻量级的数据交换格式,它简洁并且具有很好的可拓展性,容易阅读,也容易被机器解析,因此JSON成为当前最流行的数据交换格式。
JSON格式例子如下:
-
用JSON来描述一个人的属性。
-
嵌套对象:
-
数组:
-
根节点为数组
JSON由成对的key: value
序列组成。key的类型永远是字符串,而value的类型可以是:
-
数字:可表示整数或者浮点数
-
boolean:true或者false
-
null:null类型只有null一个值
-
字符串:
-
对象:使用{}定义
-
数组:使用[]定义
各种语言都有JSON的生成和解析的库,C语言使用cJson,C++则更多的使用rapidJson。
14.6.5 xml
略。
14.7 HTTPS安全通信
一般网络通信是不安全的,因为有许多中间设备可能通过类似抓包的技术,可以获取报文,如果报文中携带一些敏感的信息,比如用户名和密码信息。
如果使用对称加密技术,密钥传输的安全性同样值得怀疑,而一旦密钥泄露,加密形同虚设。
非对称加密技术可以使用的加密密钥和解密密钥是不同的,加密密钥不能用于解密,这样加密密钥泄漏了,也不影响数据安全性。这样客户端可以安全得到加密密钥,而其他人得到加密密钥无法解密。
在HTTPS中,客户端随机生成对称的加密密钥,然后通过服务器给的非对称的加密密钥,加密对称的加密密钥,然后发给服务器,后续的通信使用对称机密。
HTTPS技术使得传输过程的安全无懈可击,但是如果认为任何带HTTPS的网站就是安全的那就错了,因为有些钓鱼网站,来骗取用户的敏感信息,因此需要第三方机构来监控提供服务的服务器的安全性。HTTPS证书需要花钱购买,也有一些机构颁发免费的HTTPS证书。
有些更加严格的HTTPS通信,要求客户端也必须有证书。因为别人可以得到加密密钥,就可以实行假冒行为。银行的客户端一般需要证书,而证书保存在银行配的u盘中。
在实际的编码中,HTTPS并不需要增加多少额外的工作,就可以实现HTTPS通信。
14.8 负载均衡
负载均衡技术,可以使得多个服务器分别负担繁重的用户请求。负载均衡可以通过许多技术来实现,比如DNS、NGINX反向代理、LVS、重定向等等。
目前比较流行的有NGINX的反向代理实现负载均衡。
最后
以上就是俏皮蜜蜂为你收集整理的HTTP协议HTTP协议的全部内容,希望文章能够帮你解决HTTP协议HTTP协议所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复