莱芜网站建设哪家好,最好的网站开发系统,h5在哪里制作,河北设计公司排名参考#xff1a;HTTP协议的简介及其工作原理等 地址#xff1a;https://qingmu.blog.csdn.net/article/details/108046553?spm1001.2014.3001.5502 目录HTTP协议的简介及其工作原理1、HTTP简介1.1、什么是超文本#xff08;HyperText#xff09;?1.2、什么是URL#xff… 参考HTTP协议的简介及其工作原理等 地址https://qingmu.blog.csdn.net/article/details/108046553?spm1001.2014.3001.5502 目录HTTP协议的简介及其工作原理1、HTTP简介1.1、什么是超文本HyperText?1.2、什么是URL1.3、什么是超文本传输协议HTTP2、HTTP工作原理2.1、请求/相应交互模式2.2、HTTP的连接方式(非持久性/持久性)和无状态性HTTP的报文结构和HTTP代理1、HTTP报文结构1.1、请求报文1.2、响应报文1.3、请求报文中的一些方法1.4、响应报文中的状态码1.5、首部字段或消息头2、HTTP代理2.1、什么是HTTP用户代理2.2、使用HTTP代理的Web访问过程HTTP高效解析的方法之哈希加速HTTP高效解析方法之协议状态机协议状态机原理协议状态机的处理机制HTTP协议的简介及其工作原理
1、HTTP简介
1.1、什么是超文本HyperText?
包含有超链接Link和各种多媒体元素标记Markup的文本。这些超文本文件彼此链接形成网状Web因此又被称为网页Web Page。这些链接使用URL表示。最常用的超文本格式是超文本标记语言HTML。
1.2、什么是URL
URL即统-资源定位符(Uniform Resource Locator),用来唯一地标识万维网中的某一个文档。 URL由协议、主机和端口(默认为80)以及文件名三部分构成。 如:
1.3、什么是超文本传输协议HTTP
是一种按照URL指示,将超文本文档从一台主机(Web服务器)传输到另一台主机(浏览器)的应用层协议, 以实现超链接的功能。
2、HTTP工作原理
2.1、请求/相应交互模式
在用户点击URL为http://www.sxtyu.com/index.html的链接后浏览器和Web服务器执行以下动作
①、浏览器分析超链接中的URL
②、浏览器向DNS请求解析www.sxtyu.com的IP地址
③、DNS将解析出的IP地址202.2.16.21返回浏览器
④、浏览器与服务器建立TCP连接(80端
⑤、浏览器请求文档: GET /index.htm
⑥、服务器给出响应将文档index.html发送给浏览器
⑦、释放TCP连接
⑧、浏览器显示index.html中的内容 2.2、HTTP的连接方式(非持久性/持久性)和无状态性
2.2.1、非持久性连接
即浏览器每请求一个Web文档, 就创建一个新的连接, 当文档传输完毕后连接就立刻被释放。
HTTP1.0、HTTP0.9采用此连接方式。
对于请求的Web页中包含多个其他文档对象(如图像、音、视频等)的链接的情况于请求每个链接对应的文档都要创建新连接,效率低下。
2.2.2、持久性连接
即在一个连接中 可以进行多次文档的请求和响应。服务器在发送完响应后不立即释放连接,浏览器可以使用该连接继续请求其他文档。连接保持的时间可以由双方进行协商。
2.2.3、无状态性
是指同一个客户端(浏览器第二 _次访问同一 个Web服务器上的页面时,服务器无法知道这个客户曾经访问过。HTTP的无状态性简化了服务器的设计,使其更容易支持大量并发的HTTP请求。 HTTP的报文结构和HTTP代理
1、HTTP报文结构
1.1、请求报文
即从客户端浏览器向Web服务器发送请求报文。报文的所有字段都是ASCII码。 实例
GET /js/an.js HTTP/1.1 #请求行
Accept: */* #可接受的媒体类型
Accept-Encoding: gzip, deflate #可接受的编码
Accept-L anguage: zh-cn #接受的语言
Connection: Keep-Alive #持久连接
Host: cache.soso.com #Host
Referer: http://help.soso.com/ #引用 页面
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; InfoPath.2) #用户代理1.2、响应报文
即从Web服务器到客户机浏览器的应答。报文的所有字段都是ASCII码。 实例
HTTP/1.1200 OK #状态行.
Accept-Ranges: bytes #表示服务器端可以接受range请求
Cache-Control: max -age86400 #缓存控制时间
Content-Encoding: gzip #内容编码格式
Content-L ength: 1088 #内容长度
Content-Type: text/javascript #内容类型
Date: Thu, 18 Jun 2009 15:47:14 GMT #时间
ETag:“1902284250“ #实体标签
Expires: Fri, 19 Jun 2009 15:47:14 GMT #过期时间
L ast-Modified: Fri, 10 Oct 2008 04:13:19 GMT #最后修改日期
Server: WS CDN Server #Server名称
Vary: Accept-Encoding #告知该响应缓存时取决的方式1.3、请求报文中的一些方法
方法Method是所请求对象所进行的操作也就是一些命令。请求报文中的操作有
方法(操作)含义GET请求读取一个页面POST附加一个命名资源如Web页面HEAD请求读取一个Web页面的首部PUT请求存储一个Web页面DELETE删除Web页面TRACE用于测试要求服务器送回收到的请求CONNECT用于代理服务器OPTION查询特定选项
1.4、响应报文中的状态码
状态码:Status-code是响应报文状态行中包含的以三位数字指明特定的要求是否被满足如果没有满足原因是什么。状态码分为一下的五类
状态码含义例子1xx通知信息100服务器正在处理客户请求2xx成功200请求成功3xx重定向301页面改变了位置4xx客户端错误403禁止的页面401页面未找到5xx服务器错误500服务器内部错误503以后再试
常见的状态码 ➢200 OK ➢206 Partial Content ➢301 Moved Permanently ➢302 Found ➢304 Not Modified ➢400 Bad Request ➢403 Forbidden ➢404 Not Found ➢502 Bad Gateway ➢503 Service Unavailable ➢504 Gateway Timeout
1.5、首部字段或消息头
头(header)类型说明User- Agent请求关于浏览器和它平台的信息如Moilla5.0Accept请求客户能处理的页面的类型如text/htmlAccept-Charset请求客户可以接受的字符集如Unicode-1-1Accept-Encoding请求客户能处理的页面编码方法如gzipAccept-Language请求客户能处理的自然语言,如en(英语)zh- cn(简体中文)Host请求服务器的DNS名称。从URL中提取出来必需。Authorization请求客户的信息凭据列表Cookie请求将以前设置的Cookie送回服务器器,可用来作为会话信息Date双向消息被发送时的日期和时间Server响应关于服务器的信息如Microsoft IS/6.0Content-Encoding响应内容是如何被编码的(如gzip)Content-Language响应页面所使用的自然语言Content-Length响应以字节计算的页面长度Content-Type响应页面的MIIME类型Last-Modified响应页面最后被修改的时间和日期在页面缓存机制中意义重大Location响应指示客户将请求发送给别处即重定向到另个URLSet-Cookie响应服务器希望客户保存一个Cookie
2、HTTP代理
2.1、什么是HTTP用户代理
HTTP代理又称Web缓存或代理服务器(Proxy Server)是一种网络实体, 能代表浏览器发出HTTP请求并将最近的一些请求和响应暂存在本地磁盘中当请求的Web页面先前暂存过则直接将暂存的页面发给客户端(浏览器)无须再次访问Internet。
2.2、使用HTTP代理的Web访问过程 HTTP高效解析的方法之哈希加速
哈希加速
在我们获取到HTTP的外部请求的时候第一步去识别它所对应的请求类型然后再去获取它后面所对的URL,最后在对URL做进一步的解析。
在我们获取到了URL之后我们需要在数据库中或者文件系统中获取对应的文件也就是字符串匹配但是解析和比较字符串的速度很慢达不到我们的需求那么我们就需要加快URL的解析那么如何操作呢我们可以使用哈希加速
哈希加速把服务器自己所对应的url全部通过哈希算法把每一个url路径都算成一个数然后把输入的URL也进行哈希算法算成一个数和服务器的进行比较如果在服务器的哈希范围内并且有匹配的值就打开对应的路径所对应的文件如果哈希值匹配不上就认为此URL是错误的URL。
这样通过哈希来比较比字符串的比较快的多。
HASH解析URL链接实现
/*管理URL的对象*/
typedef struct {char url[MAX_URL_LEN]; //URLsize_t len; //长度int all; //个数UT_hash_handle hh; //HASH表
} url_t;/*HASH表的一个节点*/
typedef struct UT_hash_handle {struct UT_hash_table *tbl;void *prev; /* prev element in app order */void *next; /* next element in app order */struct UT_hash_handle *hh_prev; /* previous hh in bucket order */struct UT_hash_handle *hh_next; /* next hh in bucket order */void *key; /* ptr to enclosing structs key */unsigned keylen; /* enclosing structs key len */unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;/*HASH表*/
typedef struct UT_hash_table
{UT_hash_bucket *buckets;unsigned num_buckets, log2_num_buckets;unsigned num_items;struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element *//* in an ideal situation (all buckets used equally), no bucket would have* more than ceil(#items/#buckets) items. thats the ideal chain length. */unsigned ideal_chain_maxlen;/* nonideal_items is the number of items in the hash whose chain position* exceeds the ideal chain maxlen. these items pay the penalty for an uneven* hash distribution; reaching them in a chain traversal takes ideal steps */unsigned nonideal_items;/* ineffective expands occur when a bucket doubling was performed, but* afterward, more than half the items in the hash had nonideal chain* positions. If this happens on two consecutive expansions we inhibit any* further expansion, as its not helping; this happens when the hash* function isnt a good fit for the key domain. When expansion is inhibited* the hash will still work, albeit no longer in constant time. */unsigned ineff_expands, noexpand;uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOMuint32_t bloom_sig; /* used only to test bloom exists in external analysis */uint8_t *bloom_bv;uint8_t bloom_nbits;
#endif
}/*HASH算法*/
HASH_FIND_STR(urls, url, u);#define HASH_FIND_STR(head,findstr,out) \HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out)#define HASH_FIND(hh,head,keyptr,keylen,out) \
do { \unsigned _hf_hashv; \HASH_VALUE(keyptr, keylen, _hf_hashv); \HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \
} while (0#define HASH_VALUE(keyptr,keylen,hashv) \
do { \HASH_FCN(keyptr, keylen, hashv); \
} while (0)#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif#define HASH_JEN(key,keylen,hashv) \
do { \unsigned _hj_i,_hj_j,_hj_k; \unsigned const char *_hj_key(unsigned const char*)(key); \hashv 0xfeedbeefu; \_hj_i _hj_j 0x9e3779b9u; \_hj_k (unsigned)(keylen); \while (_hj_k 12U) { \_hj_i (_hj_key[0] ( (unsigned)_hj_key[1] 8 ) \ ( (unsigned)_hj_key[2] 16 ) \ ( (unsigned)_hj_key[3] 24 ) ); \_hj_j (_hj_key[4] ( (unsigned)_hj_key[5] 8 ) \ ( (unsigned)_hj_key[6] 16 ) \ ( (unsigned)_hj_key[7] 24 ) ); \hashv (_hj_key[8] ( (unsigned)_hj_key[9] 8 ) \ ( (unsigned)_hj_key[10] 16 ) \ ( (unsigned)_hj_key[11] 24 ) ); \\HASH_JEN_MIX(_hj_i, _hj_j, hashv); \\_hj_key 12; \_hj_k - 12U; \} \hashv (unsigned)(keylen); \switch ( _hj_k ) { \case 11: hashv ( (unsigned)_hj_key[10] 24 ); /* FALLTHROUGH */ \case 10: hashv ( (unsigned)_hj_key[9] 16 ); /* FALLTHROUGH */ \case 9: hashv ( (unsigned)_hj_key[8] 8 ); /* FALLTHROUGH */ \case 8: _hj_j ( (unsigned)_hj_key[7] 24 ); /* FALLTHROUGH */ \case 7: _hj_j ( (unsigned)_hj_key[6] 16 ); /* FALLTHROUGH */ \case 6: _hj_j ( (unsigned)_hj_key[5] 8 ); /* FALLTHROUGH */ \case 5: _hj_j _hj_key[4]; /* FALLTHROUGH */ \case 4: _hj_i ( (unsigned)_hj_key[3] 24 ); /* FALLTHROUGH */ \case 3: _hj_i ( (unsigned)_hj_key[2] 16 ); /* FALLTHROUGH */ \case 2: _hj_i ( (unsigned)_hj_key[1] 8 ); /* FALLTHROUGH */ \case 1: _hj_i _hj_key[0]; \} \HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
} while (0)#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
do { \(out) NULL; \if (head) { \unsigned _hf_bkt; \HASH_TO_BKT(hashval, (head)-hh.tbl-num_buckets, _hf_bkt); \if (HASH_BLOOM_TEST((head)-hh.tbl, hashval) ! 0) { \HASH_FIND_IN_BKT((head)-hh.tbl, hh, (head)-hh.tbl-buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \} \} \
} while (0)HASH_ADD_STR(urls, url, u); 那么我们如何维护一个HASH表呢
添加一个HASH int add_url(const char *url)
{url_t *u;if (!url || strlen(url) MAX_URL_LEN) return 0;pthread_rwlock_wrlock(rwlock);HASH_FIND_STR(urls, url, u);if (u) {pthread_rwlock_unlock(rwlock);return 0;}u (url_t *)calloc(1, sizeof(url_t));strncpy(u-url, url, MAX_URL_LEN - 1);u-len strlen(u-url);if (u-url[u-len - 1] URL_SPLIT) {//u-url[u-len - 1] 0;u-all 1;}HASH_ADD_STR(urls, url, u);pthread_rwlock_unlock(rwlock);return 1;
}判断URL在不在HASH表中
int has_url(const char *url)
{char tmp[MAX_URL_LEN];char *start, *end, *pos;size_t ul;url_t *u;if (!url) {return 0;}ul strlen(url); if (ul MAX_URL_LEN) {return 0;}memset(tmp, 0x00, sizeof(tmp));pos tmp;start (char *)url;pthread_rwlock_rdlock(rwlock);HASH_FIND_STR(urls, url, u);if (u) {pthread_rwlock_unlock(rwlock);return 1;}end strchr(start, URL_SPLIT);for (; end; end strchr(start, URL_SPLIT)) {memcpy(pos, start, end - start 1);HASH_FIND_STR(urls, tmp, u);if (u u-all) {pthread_rwlock_unlock(rwlock);return 1;}pos (end - start 1);start end 1;}pthread_rwlock_unlock(rwlock);return 0;
}删除一个URL
int del_url(const char *url)
{url_t *u;if (!url || strlen(url) MAX_URL_LEN) {return 0;}pthread_rwlock_wrlock(rwlock);HASH_FIND_STR(urls, url, u);if (u) {HASH_DEL(urls, u);pthread_rwlock_unlock(rwlock);return 1;}pthread_rwlock_unlock(rwlock);return 0;
}HTTP高效解析方法之协议状态机
协议状态机原理
平时我们解析单个的URL的时候都是一个线程从头解析到尾一个线程完成了所有的事情 协议状态机就是把这一件事情分成很多份分发给更多的线程去解决这样当并发量很大的时候就能很好快速的处理完美解决了高并发的问题。
协议状态机的每一步都存在输出和跳转下面我们以一个正确的解析方式来分析一下协议状态机
判断方法:判断HTTP协议的第一个字母是G P 每个状态机都有一个跳转条件和输出结果 确定方法 确定当前状态根据状态的类型跳转到不同方法的处理状态 每一步处理完之后我们都会得到一个状态正确或错误或其他我们就跳转到对应的步骤。
我们分成多个线程来处理当数据量特别大的时候做并发性的处理非常适合特别是当流水线在满载运行的时候效率是非常高的。
相当于是面积换速度的一种方法。
协议状态机的处理机制
1.定义一个协议状态集合
状态结构体包含了所有状态随着设计慢慢补充
enum state{ s_dead 1 /* important that this is 0 */, s_start_req_or_res, s_res_or_resp_H, s_start_res, s_res_H, s_res_HT, s_res_HTT, s_res_HTTP, s_res_http_major, s_res_http_dot, s_res_http_minor, s_res_http_end, s_res_first_status_code, s_res_status_code, s_res_status_start, s_res_status, s_res_line_almost_done, s_start_req, s_req_method, s_req_spaces_before_url, s_req_schema, s_req_schema_slash, s_req_schema_slash_slash, s_req_server_start, s_req_server, s_req_server_with_at, s_req_path, s_req_query_string_start, s_req_query_string, s_req_fragment_start, s_req_fragment, s_req_http_start, s_req_http_H, s_req_http_HT, s_req_http_HTT, s_req_http_HTTP, s_req_http_major, s_req_http_dot, s_req_http_minor, s_req_http_end, s_req_line_almost_done, s_header_field_start, s_header_field, s_header_value_discard_ws, s_header_value_discard_ws_almost_done, s_header_value_discard_lws, s_header_value_start, s_header_value, s_header_value_lws, s_header_almost_done, s_chunk_size_start, s_chunk_size, s_chunk_parameters, s_chunk_size_almost_done, s_headers_almost_done, s_headers_done, s_chunk_data, s_chunk_data_almost_done, s_chunk_data_done, s_body_identity, s_body_identity_eof, s_message_done};2. 输出结构体
struct http_parser {/** PRIVATE **/unsigned int type : 2; /* enum http_parser_type */unsigned int flags : 8; /* F_* values from flags enum; semi-public */unsigned int state : 7; /* enum state from http_parser.c */unsigned int header_state : 7; /* enum header_state from http_parser.c */unsigned int index : 7; /* index into current matcher */unsigned int lenient_http_headers : 1;uint32_t nread; /* # bytes read in various scenarios */uint64_t content_length; /* # bytes in body (0 if no Content-Length header) *//** READ-ONLY **/unsigned short http_major;unsigned short http_minor;unsigned int status_code : 16; /* responses only */unsigned int method : 8; /* requests only */unsigned int http_errno : 7;/* 1 Upgrade header was present and the parser has exited because of that.* 0 No upgrade header present.* Should be checked when http_parser_execute() returns in addition to* error checking.*/unsigned int upgrade : 1;/** PUBLIC **/void *data; /* A pointer to get hook to the connection or socket object */
};3.状态图跳转逻辑
#define CURRENT_STATE() p_state
#define UPDATE_STATE(V) p_state (enum state) (V);switch (CURRENT_STATE()) { //不同的状态干不同的事s_header_almost_done :parser-flags 0;parser-content_length ULLONG_MAX;UPDATE_STATE(s_start_req); //跳转break s_header_value_lws : }