king-etc / king-blog Goto Github PK
View Code? Open in Web Editor NEWemmmm
emmmm
std::thread T1;
std::thread T2(func,args...)
std::thread T3(T2)
注意 被标注delete 应舍弃std::thread T4(std::move(T2))
注意 std::move之后 并不存在实例化之后的T2了,类似于std::string a="Example;"
std:string b(std::move(a));
string a
。std::thread T5 = std::thread(func,args)
std::thread T6 = T5
注意 被标注delete 应舍弃函数名 | 功能 | 返回值 |
---|---|---|
get_id() |
获取线程ID | std::thread::id |
join() |
阻塞当前线程直到调用的线程执行完毕 | void |
joinable() |
检查线程是否可被join | bool |
detach() |
使该线程与当前线程分离单独运行 | void |
swap() |
交换线程对象所代表的底层句柄 | void |
native_handle() |
返回线程句柄 | native_handle_type |
hardware_concurrency |
当前平台所支持的并发数目 | static unsigned int |
this_thread
函数名 | 功能 | 返回值 |
---|---|---|
yield() |
当前进程放弃执行 | void |
sleep_until |
线程休眠直到指定的时间点 | void |
sleep_for |
线程休眠指定的时间 | void |
join() 和 detach() 的区别
join() 会阻塞当前进程等待指定进程结束。在此期间 joinable()==1;
detach() 一旦脱离 除非使用其他方式(信号量etc) 否则无法获知运行状态,在此期间 joinable()==0;
thread 构建之后会立即运行。
此后的join() detach 只能在线程运行期间有效。
HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点。
本文介绍 HTTP 协议的历史演变和设计思路。
HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。
最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET。
GET /index.html
上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页index.html。
协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。
<html>
<body>Hello World</body>
</html>
服务器发送完毕,就关闭TCP连接。
1996年5月,HTTP/1.0 版本发布,内容大大增加。
首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。
其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。
再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
下面是一个1.0版的HTTP请求的例子。
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
可以看到,这个格式与0.9版有很大变化。
第一行是请求命令,必须在尾部添加协议版本(HTTP/1.0)。后面就是多行头信息,描述客户端的情况。
服务器的回应如下。
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
回应的格式是"头信息 + 一个空行(\r\n) + 数据"。其中,第一行是"协议版本 + 状态码(status code) + 状态描述"。
关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。
下面是一些常见的Content-Type字段的值。
text/plain
text/html
text/css
image/jpeg
image/png
image/svg+xml
audio/mp4
video/mp4
application/javascript
application/pdf
application/zip
application/atom+xml
这些数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。
除了预定义的类型,厂商也可以自定义类型。
application/vnd.debian.binary-package
上面的类型表明,发送的是Debian系统的二进制数据包。
MIME type还可以在尾部使用分号,添加参数。
Content-Type: text/html; charset=utf-8
上面的类型表明,发送的是网页,而且编码是UTF-8。
客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。
Accept: */*
上面代码中,客户端声明自己可以接受任何格式的数据。
MIME type不仅用在HTTP协议,还可以用在其他地方,比如HTML网页。
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- 等同于 -->
<meta charset="utf-8" />
由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。
Accept-Encoding: gzip, deflate
HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。
TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。
为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。
Connection: keep-alive
这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。
Connection: keep-alive
一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。
1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。
1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。
客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。
Connection: close
目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。
1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。
一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。
Content-Length: 3495
上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。
在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。
使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。
对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。
因此,1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。
Transfer-Encoding: chunked
每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。下面是一个例子。
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
1.1版还新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。
另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。
Host: www.example.com
有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。
虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。
为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。
2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。
这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。
2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。
HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧"(frame):头信息帧和数据帧。
二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。
HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"。
举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。
这样双向的、实时的通信,就叫做多工(Multiplexing)。
因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。
客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。
HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。
常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。
Journey to HTTP/2, by Kamran Ahmed
HTTP, by Wikipedia
HTTP/1.0 Specification
HTTP/2 Specification
(完)
因为 满足2的n次方的数 二进制表现为 10...0的形式。取反之后为01...1的形式 。所以满足
(Y != 0) && ((Y & (~Y + 1)) == Y)==true
或者
((Y&(Y-1))&&(Y!=0))==0
Permissions 0644 for '***.pem' are too open.
chmod 600 ***.pem
ssh -i identity_file user@hostname
柔性数组(Flexible Array)也叫伸缩性数组
柔性数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建柔性数组。
柔性数组有什么用途 ?
它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。
用法 :在一个结构体的最后 ,申明一个长度为空的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名
本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们
可以进行动态分配,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!
对于柔性数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:
typedef struct _SoftArray
{
Int len;
int array[];
}SoftArray;
这样的变长数组常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量,比如我要发送1024字节的数据,如果用定长包,假设定长包的长度为2048,就
会浪费1024个字节的空间,也会造成不必要的流量浪费。
zip -s 100m -r file.zip foo/
zip existing.zip --out new.zip -s 50m
合并文件
zip -s 0 split.zip --out single.zip
解压文件
unzip single.zip
class MyObject
{
char c;
int i;
short s;
}
alignment = 4;
内存分布:
0|1|2|3
c|
i------|
s--|
class MyObject
{
char c;
alignas(8) int i;
short s;
}
alignment = 4;
内存分布为
0|1|2|3|4|5|6|7
c|
i------|s--|
列出标签
git tag
列出特定的标签
git tag -l 'v0.1*'
创建标签(lightweight)
git tag -a "tag-name"
创建标签(annotated)
git tag -a "tag-name" -m 'Notions'
创建标签(指定提交)
git tag -a "tag-name" commit-hash
删除标签
git tag -d "tag-name"
上传标签
git push origin "tag-name"
删除远程标签
git push origin :refs/tags/"tag-name"
git branch
-v 最后一次提交信息git checkout (-b) "branch-name"
-b 新建分支并切换git branch -d "branch-name"
-D 强制删除git merge "branch-name"
讲branch-name合并到当前分支git branch --no-merged
C++规定=,[ ],(),->这四个运算符只能被重载为类的非静态成员函数,其他的可以被友元重载,主要是因为其他的运算符重载函数都会根据参数类型或数目进行精确匹配,这四个不具有这种检查的功能,用友元定义就会出错。
operation | map | unordered_map |
---|---|---|
Ordering | increasing order (by default) | No ordering |
Implementation | Self balancing BST (RBT) | Hash Table |
search time | log(n) | O(1) -> Average O(N)-> Worst Case |
Insertion time | log(n) + Rebalance | Same as search |
Deletion time | log(n) + Rebalance | Same as search |
std::map<int, std::string> ismap;
isunordered[100] = "test000";
isunordered[10] = "test001";
isunordered[110] = "test002";
isunordered[9] = "test003";
isunordered[1100] = "test004";
isunordered[107] = "test005";
ismap[100] = "test000";
ismap[10] = "test001";
ismap[110] = "test002";
ismap[9] = "test003";
ismap[1100] = "test004";
ismap[107] = "test005";
std::cout << "unordered :" << std::endl;
for (auto x : isunordered)
{
std::cout << x.first << " : " << x.second.c_str() << std::endl;
}
std::cout << "map :" << std::endl;
for (auto x : ismap)
{
std::cout << x.first << " : " << x.second.c_str() << std::endl;
}
Result :
unordered :
100 : test000
10 : test001
110 : test002
9 : test003
1100 : test004
107 : test005
map :
9 : test003
10 : test001
100 : test000
107 : test005
110 : test002
1100 : test004
-- 0 -- | -- 1 -- | -- 2 -- | -- 3 -- | -- 4 -- | -- 5 -- | -- -- |
---|---|---|---|---|---|---|
-- 1 -- | -- 2 -- | -- 3 -- | -- 4 -- | -- 5 -- | -- 6 -- | |
begin | -- 1 -- | -- 2 -- | -- pos -- | -- 4 -- | -- 5 -- | end |
-- 0 -- | -- 1 -- | -- 2 -- | -- 3 -- | -- 4 -- | -- 5 -- | -- -- |
---|---|---|---|---|---|---|
-- 1 -- | -- 2 -- | -- 3 -- | -- 4 -- | -- 5 -- | -- 6 -- | |
rend | -- 1 -- | -- 2 -- | -- rpos -- | -- 4 -- | -- 5 -- | rbegin |
#原因
如果将一个迭代器转化为reverse迭代器时会发现返回值不同.这不是bug 这是特性, (侯捷STL第九章迭代器说明)
导致这个性质是因为区间的半开性.为了指出容器内所有元素,我们需要采用"最末元素的下一位置".然而对reverse迭代器而言,这个位置位于第一元素之前.糟糕的是,这个元素可能并不存在.因为容器并不要求其第一元素之前的位置也合法.
为此 reverse 迭代器的设计者运用了一个小技巧 : 他们实际倒置了"半开原则". Reverse 迭代器所定义的区间并不包括起点,反倒是包括了终点.然而逻辑上其行为一如往前
这样就明白了.也就是 当rpos 指向一个物理位置(element) 这是其value 是该物理位置前一个元素的值. 当访问rbegin()时 该pos位于end() 返回end()之前元素的值.
auto pos = rpos.base()
#include <iostream>
struct S {
// 通常将占用 2 字节:
// 3 位:b1 的值
// 5 位:不使用
// 6 位:b2 的值
// 2 位:b3 的值
unsigned char b1 : 3;
unsigned char :0; // 开始新字节
unsigned char b2 : 6;
unsigned char b3 : 2;
};
位域中的位数决定其能保存的数值极限
多个相邻位域通常可以打包在一起
但 不能跨字节(这个存疑 某些平台可以)
特殊的零大小无名位域可用于强行打破填充。它指定下个位域始于新的字节开始
位域的类型只能似乎静态数据成员
位域不能是静态数据成员
没有位域纯右值 也就是 左值到右值转换始终生成位域底层类型的对象。
如果位域设置的位大小 超过一个字节大小,则多余的位为占位。(VC测试报错。)
std::ifstream ifs(filename, std::ios::binary);
std::string buffer;
if (ifs.is_open())
{
buffer.resize(ifs.seekg(0, std::ios::end).tellg());
ifs.seekg(0, std::ios::beg).read(&buffer[0], static_cast<std::streamsize>(buffer.size()));
return buffer;
}
std::ifstream ifs(filename, std::ios::binary);
rturn string((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
ifstream ifs;
ifs.open(filename, std::ios::binary);//open the input file
stringstream strStream;
strStream << ifs.rdbuf();
return strStream.str();
以上省略判断文件打开失败情况和关闭文件.
根据测试(VS 2019 community)
read_0 time is : 282,039,300 number : 229799858
read_1 time is : 1,934,362,200 number : 229799858
read_2 time is : 1,656,453,300 number : 229799858
预先分配足量内存是这三种方法时间消耗的关键. 使用vector代替string速度会提高20%左右
使用文本方式打开速度会快于二进制打开.原因未知,但是对于二进制文件会出现截断情况.需要注意.
logpath=log/mongodb.log
logappend=true
//日志写入方式
fork=true
join()
等待线程结束。阻塞状态。detach()
该线程与执行该线程的对象分离。独立运行,无法获知其运行状态。不过 joinable()
返回 false
或者运行错误时抛出 std::system_error
注意。当我测试这个函数时 会产生 该线程未完成但程序流程直接正常结束的问题。如果使用这个函数务必检测其状态。1、#echo "" > test.txt(文件大小被截为1字节)
2、# > test.txt(文件大小被截为0字节)
3、#cat/dev/null > test.txt(文件大小被截为0字节)
内存的基本单位是byte,64位处理器一次可以提取8byte(64位)数据,32位处理器一次读取4byte(32位)数据.这样计算机就会对基本的数据类型的合法地址做出一些限制,
| A B C D E F G H | I G K L M M O P |
如果希望读取A B C D E F G H
那么读取一次就可以,I G K L M M O P
亦然,
若希望读取 F G H I G K L M
那么一次读取是不可行的.必须读取两次才能得到.
F G H I G K L M
,这时需要读取两次.不同平台的对齐方式可能不同,所以通信时可能会发生错乱
#pragma pack(N) //设置N字节对齐
#pragma pack() //还原默认对齐
__attribute__
__attribute__((aligned (n))) //让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
__attribute__ ((packed)) //取消结构在编译过程中的优化对齐,也可以认为是1字节对齐。
#define NAME king
#define <宏名>(参数)<宏体>
#define min(x,y)(x>y)?y:x
#define Conn(a,b) x##b
#define SUM(a,b) printf(#a " + "#b" = %d\n",((a) + (b)))
#define PR(...) printf(__VA_ARGS__)
ls -lth /var/spool/mail
cat /dev/null > /var/spool/mail/root
echo "unset MAILCHECK" >> /etc/profile
source /etc/profile
whereis sudoers
chmod u+w /etc/sudoers
"user-name" ALL=(ALL)ALL
chmod u-w /etc/sudoers
tar [required argument][optional argument][file]
参数名 | 解释 |
---|---|
-A | 新增压缩文件到已存在的压缩 |
-B | 设置区块大小 |
-W | 确认压缩文件的正确性 |
-Z | 支持compress解压文件 |
-c | 设立新的压缩文件 |
-d | 记录文件的差别 |
-j | 支持bzip2解压文件 |
-k | 保留原有文件不覆盖 |
-l | 文件系统边界设置 |
-m | 保留文件不被覆盖 |
-r | 添加文件到已经压缩的文件 |
-t | 显示压缩文件的内容 |
-u | 添加改变了和现有的文件到已经存在的压缩文件 |
-v | 显示操作过程 |
-x | 从压缩文件中提取文件 |
-z | 支持gzip解压文件 |
可选参数 | |
-C | 切换到指定目录 |
-b | 设置区块数目 |
-f | 指定压缩文件 |
--help | 显示帮助信息 |
--version | 显示版本信息 |
tunctl -d <虚拟网卡名>
ifconfig <网桥名>down
//卸载
brctl delbr <网桥名>
//删除
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.