HTTP协议简介
- 超文本传输协议是一种用于分布式、协作式和超媒体信息系统的应用层协议。
- HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(一般基于TCP)。客户端发起一个HTTP请求到服务器上指定端口(默认端口为80),这个客户端被称为用户代理程序(user agent)。应答服务器被称为源服务器(origin server)。在用户代理和源服务器中间可能存在多个“中间层”,比如代理服务器、网关或者隧道(tunnel)
- HTTP可以在任何互联网协议上,或其他网络上实现。HTTP假定其下层协议提供可靠的传输。任何能够提供这种保证的协议都可以被其使用
- 由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 OK",以及返回的内容,如请求的文件、错误消息、或者其它信息。
HTTP工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
- 客户端——发出连接服务器请求
- 客户端——发送HTTP请求。
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。 - 服务器——服务器接受请求并返回HTTP响应。
一个响应由状态行、响应头部、空行和响应数据4部分组成。 - 服务器——释放连接TCP连接。
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求 - 客户端——解析反馈的内容
一次http请求之后,http协议1.1版本不会直接就断开了,而是等几秒钟,等着用户有后续的操作,如果用户在这几秒钟之内有新的请求,那么还是通过之前的连接通道来收发消息,如果过了这几秒钟用户没有发送新的请求,那么就会断开连接,这样可以提高效率,减少短时间内建立连接的次数,因为建立连接也是耗时的,默认的好像是3秒中现在,但是这个时间是可以通过咱们后端的代码来调整的,自己网站根据自己网站用户的行为来分析统计出一个最优的等待时间。
HTTP请求方式
- OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性 - HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。用于获取报文头 - GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。 - POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 - PUT
向指定资源位置上传其最新内容 - DELETE
请求服务器删除Request-URL所标识的资源 - TRACE
回显服务器收到的请求,主要用于测试或诊断 - CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
GET与POST方法区别:
- 在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交
- GET方式提交的数据最多只能有1024字节,而POST则没有此限制
- 使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。
HTTP状态码
状态代码的第一个数字代表当前响应的类型:
- 1xx消息——请求已被服务器接收,继续处理
- 2xx成功——请求已成功被服务器接收、理解、并接受
- 3xx重定向——需要后续操作才能完成这一请求
- 4xx请求错误——请求含有词法错误或者无法被执行
- 5xx服务器错误——服务器在处理某个正确请求时发生错误
URL解析
超文本传输协议(HTTP)的统一资源定位符将从因特网获取信息的五个基本元素包括在一个简单的地址中:
- 传送协议。层级URL标记符号(为[//],固定不变)
- 服务器。(通常为域名,有时为IP地址)
- 端口号。(以数字方式表示,若为HTTP的默认值“:80”可省略)
- 路径。(以“/”字符区别路径中的每一个目录名称)
- 查询。(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题)片段。以“#”字符为起点
例子:
以http://www.luffycity.com:80/news/index.html?id=250&page=1 为例, 其中:
http,是协议;
www.luffycity.com,是服务器
80,是服务器上的默认网络端口号
?id=250&page=1,是查询数据
找了一个基于TCP协议,实现HTTP传输的code,修改一下生成一个测试demo:
my_tcpclient.c
#include "my_tcpclient.h"
int main(){
my_tcpclient client;
int flags = 1;
char *response = NULL;
printf("开始组包\n");
while(flags){
my_tcpclient_create(&client,"10.100.10.24",18080);
if(http_post(&client,"/esim-lpa-server/lpa/polling?","data=89086030202200000019000037012045",&response)){
printf("失败!\n");
exit(2);
}
printf("响应:\n%d:%s\n",strlen(response),response);
flags = 0;
}
free(response);
return 0;
}
my_tcpclient.h
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define __DEBUG
#ifdef __DEBUG
#define DEBUG(...) printf(__VA_ARGS__)
#else
#define DEBUG(...)
#endif
#define BUFFER_SIZE 1024
/*
@socket
@remote_port
@remote_ip
@sockaddr_in
@connected flag
*/
typedef struct _my_tcpclient{
int socket;
int remote_port;
char remote_ip[16];
struct sockaddr_in _addr;
int connected;
} my_tcpclient;
int my_tcpclient_create(my_tcpclient