目录
1.ghttp数据结构族谱
本库中使用的数据结构还是非常清晰的,结构体以及枚举数据也不是太多,如图整个数据结构族谱非常的清晰
2.结构体详解
ghttp代码中维护一个全局的结构体struct _ghttp_request,这里面包含了所有的操作数据,包括url、代理信息、请求、应答以及网络等信息
struct _ghttp_request
{
http_uri *uri;//请求URL
http_uri *proxy;//请求代理的URL
http_req *req;//request内容
http_resp *resp;//应答结构体
http_trans_conn *conn; //底层网络数据
const char *errstr;//错误字符串
int connected;//socket句柄
ghttp_proc proc;//处理项
char *username;//用户名
char *password;//密码
char *authtoken;//authtoken认证字段
char *proxy_username;//代理用户名
char *proxy_password;//代理密码
char *proxy_authtoken;//代理authtoken认证字段
};
2.1 http_uri
将传入的url字符串解析之后赋值到该结构体进行处理
/* URL结构体 */
typedef struct http_uri_tag
{
char *full; /* 传入的URL,比如:http://1.1.1.1:80/api/login */
char *proto;/*从URL中解析出来即:http */
char *host;/* 从URL中解析出来的IP或者域名,如full中的1.1.1.1 */
unsigned short port;/* 从URL中解析出来的端口,如full中的80 */
char *resource;/* 从URL中解析出来的请求资源,如full中的/api/login */
} http_uri;
2.2 http_req
这里面封装了请求的所有信息,包括请求方法、协议版本、服务器的IP地址、端口、接口等数据,此外还有协议头和请求报文体
typedef struct http_req_tag {
http_req_type type;//请求方法
float http_ver;//协议版本
char *host;//服务器IP
char *full_uri;//请求的URL
char *resource;//请求接口
char *body;//请求报文体
int body_len;//请求body长度
http_hdr_list *headers;//请求协议头部
http_req_state state;//请求状态
} http_req;
2.2.1 http_req_type
这是个数据枚举类型,枚举了所支持的方法,根据HTTP标准,HTTP请求可以使用多种请求方法。
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
此外:
- Mkcol:创建集合
- PropFind和PropPatch:针对资源和集合检索和设置属性;
- Copy和Move:管理命名空间上下文中的集合和资源;
- Lock和Unlock:改写保护
typedef enum http_req_type {
http_req_type_get = 0,//请求指定的页面信息,并返回实体主体
http_req_type_options,//允许客户端查看服务器的性能
http_req_type_head,//类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
http_req_type_post,//向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改
http_req_type_put,//从客户端向服务器传送的数据取代指定的文档的内容
http_req_type_delete,//请求服务器删除指定的页面
http_req_type_trace,//回显服务器收到的请求,主要用于测试或诊断
http_req_type_connect,//HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
http_req_type_propfind,
http_req_type_proppatch,
http_req_type_mkcol,
http_req_type_copy,
http_req_type_move,
http_req_type_lock,
http_req_type_unlock
} http_req_type;
文中注释了常用的方法,后面的不常用的,笔者也没有使用过所有没有增加详细说明。
2.2.2 http_hdr_list
http_hdr_list这里记录的是协议头,根据用户的输入先保存在这个list里面,这个更类似于一个map类型,里面是key-val类似的键值对。
#define HTTP_HDRS_MAX 256
//协议头部结构体,最大256
typedef struct http_hdr_list_tag
{
char *header[HTTP_HDRS_MAX];
char *value[HTTP_HDRS_MAX];
} http_hdr_list;
2.2.3 http_req_state
http_req_state是请求操作的一个状态,记录了当前正在操作的项
typedef enum http_req_state_tag {
http_req_state_start = 0,
http_req_state_sending_request,//发送请求
http_req_state_sending_headers,//发送请求头部
http_req_state_sending_body//发送请求body
} http_req_state;
2.3 http_resp
应答报文,里面包含了应答的协议版本、状态码和状态描述,此外还有返回的报文头以及报文体和头部状态body状态等信息,其中headers字段不再叙述,在http_req结构体中已经有过说明
typedef struct http_resp_tag
{
float http_ver;//协议版本
int status_code;//请求返回的状态码
char *reason_phrase;//请求返回的状态 比如OK
http_hdr_list *headers;//返回的协议头
char *body;//返回的报文body部分
int body_len;//返回的报文body部分长度
int content_length;//content数据长度
int flushed_length;//刷新出来的数据长度
http_resp_header_state header_state;//头部状态
http_resp_body_state body_state;//body状态
} http_resp;
2.3.1 http_resp_header_state
这是个枚举类型,里面是应答报文操作的状态,目前只有read状态
typedef enum http_resp_header_state_tag
{
http_resp_header_start = 0,
http_resp_reading_header
} http_resp_header_state;
2.3.2 http_resp_body_state
应答报文体状态
typedef enum http_resp_body_state_tag
{
http_resp_body_start = 0,
http_resp_body_read_content_length,
http_resp_body_read_chunked,
http_resp_body_read_standard
} http_resp_body_state;
2.4 http_trans_conn
这里记录的网络操作信息,从最底层的主机信息、网络信息、socket以及到操作中的缓冲区信息都有描述
typedef struct http_trans_conn_tag {
struct hostent *hostinfo;//主机信息
struct sockaddr_in saddr;//网络通信结构体
char *host;//ip地址
char *proxy_host;//代理ip地址
int sock;//socked句柄
short port;//端口
short proxy_port;//代理端口
http_trans_err_type error_type;//错误类型
int error;//错误码
int sync; /* 是否同步*/
char *io_buf; /* 缓冲区*/
int io_buf_len; /* 缓冲区大小 */
int io_buf_alloc; /* 已使用缓冲区大小 */
int io_buf_io_done; /* 缓冲区滑动窗口已使用大小 */
int io_buf_io_left; /* 预留数据缓冲区大小 */
int io_buf_chunksize; /* 读入或者数据块大小 */
int last_read; /* 最后一次读取的大小 */
int chunk_len; /* 块长度 */
char *errstr; /* 错误描述 */
} http_trans_conn;
2.4.1 struct hostent
主机信息结构体,记录的是主机相关的内容
struct hostent
{
char *h_name; //正式主机名
char **h_aliases; //主机别名
int h_addrtype; //主机IP地址类型:IPV4-AF_INET
int h_length; //主机IP地址字节长度,对于IPv4是四字节,即32位
char **h_addr_list; //主机的IP地址列表
};
#define h_addr h_addr_list[0] //保存的是IP地址
2.4.2 struct sockaddr_in
网络通信结构体,是为了socket服务的
struct sockaddr_in
{
sa_family_t sin_family;//Address family一般来说AF_INET(地址族)PF_INET(协议族)
uint16_t sin_port;//16位TCP/UDP端口号
struct in_addr sin_addr;//32位IP地址
unsigned char sin_zero[8];//预留
};
struct in_addr
{
In_addr_t s_addr;//32位IPv4地址
};
2.4.3 http_trans_err_type
这是一个枚举数据类型,描述的是网络中的错误类型
typedef enum http_trans_err_type_tag {
http_trans_err_type_host = 0,
http_trans_err_type_errno
} http_trans_err_type;
3 小结
至此ghttp中的数据结构基本就介绍完了,这个库里面的数据结构设计的还是比较清晰的,但是个人使用起来的感觉就是有些字段冗余比较大,有些繁琐,不确定代码开发人员的真实意图是什么,还是这样做的目的是为了模块化更清晰一些呢,尚且还没有悟透这层含义。