分类 默认分类 下的文章

ssl 编程服务器和客户端完整demo c++版,编译环境:cent os 64, g++

安装openssl:

yum search opensll #查找可用的openssl开发包
yum install opensll-devel.x86_64 #从查找结果中选择安装 devel 版本
生成ca文件和key文件,供服务器使用

openssl genrsa -out privkey.pem 2048
openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
服务器代码:

include <stdio.h>

include <stdlib.h>

include <errno.h>

include <string.h>

include <sys/types.h>

include <netinet/in.h>

include <sys/socket.h>

include <sys/wait.h>

include <unistd.h>

include <arpa/inet.h>

include <openssl/ssl.h>

include <openssl/err.h>

define MAXBUF 1024

const int s_myport = 8081;

int main(int argc, char **argv)
{

int sockfd, new_fd;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
char buf[MAXBUF + 1];
SSL_CTX *ctx;

SSL_library_init();
OpenSSL_add_all_algorithms();

SSL_load_error_strings();

ctx = SSL_CTX_new(SSLv23_server_method());

if (ctx == NULL) 
{
    ERR_print_errors_fp(stdout);
    printf("---1\n");
    exit(1);
}

if (SSL_CTX_use_certificate_file(ctx, argv[1], SSL_FILETYPE_PEM) <= 0)
{
    ERR_print_errors_fp(stdout);
     printf("---2:{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n", argv[1]);
    exit(1);
}

if (SSL_CTX_use_PrivateKey_file(ctx, argv[2], SSL_FILETYPE_PEM) <= 0)
{
    ERR_print_errors_fp(stdout);
     printf("---3:{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n", argv[2]);
    exit(1);
}

if (!SSL_CTX_check_private_key(ctx)) 
{
     printf("---4\n");
    ERR_print_errors_fp(stdout);
    exit(1);
}


if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) 
{
     printf("---5\n");
    perror("socket");
    exit(1);
} 
else
{
    printf("socket created\n");
}

bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(s_myport);
my_addr.sin_addr.s_addr = INADDR_ANY;

if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) 
{
    perror("bind");
    exit(1);
} 
else
{
    printf("binded\n");
}
unsigned int lisnum = 1;
if (listen(sockfd, lisnum) == -1) 
{
    perror("listen");
    exit(1);
} 
else
{
    printf("begin listen\n");
}
 
while (1) 
{
    SSL *ssl;
    len = sizeof(struct sockaddr);

    if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1)
    {
        perror("accept");
        exit(errno);
    } 
    else
    {
    printf("server: got connection from {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s, port {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d, socket {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);
    }

    ssl = SSL_new(ctx);

    SSL_set_fd(ssl, new_fd);

    if (SSL_accept(ssl) == -1) 
    {
        perror("accept");
        close(new_fd);
        break;
    }


    bzero(buf, MAXBUF + 1);
    strcpy(buf, "hello, this is server");

    len = SSL_write(ssl, buf, strlen(buf));

    if (len <= 0) 
    {
        printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s,{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d,{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n",buf, errno, strerror(errno));
        goto finish;
    } 
    else
    {
        //printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s, {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d\n", buf, len);
    }

    bzero(buf, MAXBUF + 1);

    len = SSL_read(ssl, buf, MAXBUF);
    if (len > 0)
    {
        printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s, {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d\n", buf, len);
    }
    else
    {
        printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d,{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s'\n", errno, strerror(errno));
    }

finish:

    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(new_fd);
}


close(sockfd);

SSL_CTX_free(ctx);
return 0;

}
客户端代码:

include <stdio.h>

include <string.h>

include <errno.h>

include <sys/socket.h>

include <resolv.h>

include <stdlib.h>

include <netinet/in.h>

include <arpa/inet.h>

include <unistd.h>

include <openssl/ssl.h>

include <openssl/err.h>

define MAXBUF 1024

void ShowCerts(SSL * ssl)
{

X509 *cert;
char *line;

cert = SSL_get_peer_certificate(ssl);
if (cert != NULL)
{
    printf("show:\n");
    line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
    printf("one: {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n", line);
    free(line);
    line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
    printf("two {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n", line);
    free(line);
     
    char commonName [512] = {0};
    X509_NAME * name = NULL;
    name = X509_get_subject_name(cert);
    X509_NAME_get_text_by_NID(name, NID_commonName, commonName, 512);
    printf("debug-name:{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n", commonName);
     
    X509_free(cert);
} 
else
{
    printf("error\n");
}

}

int main(int argc, char **argv)
{

int sockfd, len;
struct sockaddr_in dest;
char buffer[MAXBUF + 1];
SSL_CTX *ctx;
SSL *ssl;

if (argc != 3)
{
    printf("please use command:{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s 127.0.0.1 8081\n", argv[0]);
    exit(0);
}


SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL) 
{
    ERR_print_errors_fp(stdout);
    exit(1);
}


if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
{
    perror("Socket");
    exit(errno);
}
printf("socket created\n");


bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(argv[2]));
if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
    perror(argv[1]);
    exit(errno);
}
printf("address created\n");


if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
    perror("Connect ");
    exit(errno);
}
printf("server connected\n");


ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);

if (SSL_connect(ssl) == -1)
{
    ERR_print_errors_fp(stderr);
}
else
{
    printf("Connected with {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s encryption\n", SSL_get_cipher(ssl));
    ShowCerts(ssl);
}


bzero(buffer, MAXBUF + 1);

len = SSL_read(ssl, buffer, MAXBUF);
if (len > 0)
{
    printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s:{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d\n", buffer, len);
}
else
{
    printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d,{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s'\n", errno, strerror(errno));
    goto finish;
}
bzero(buffer, MAXBUF + 1);
strcpy(buffer, "hello this is client.");

len = SSL_write(ssl, buffer, strlen(buffer));
if (len < 0)
{
    printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s,{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d,{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s\n", buffer, errno, strerror(errno));
}
else
{
    //printf("{b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}s, {b75a474a571334bb08f4db31fa80d7688c6401b1dcf97fb55e06ed241b59472c}d\n", buffer, len);
}

finish:

SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return 0;

}
编译命令:

gcc -Wall -lssl server.cpp -lstdc++ -o server
gcc -Wall -lssl client.cpp -lstdc++ -o client
执行:

./server cacert.pem privkey.pem
./client 127.0.0.1 8081
OK,这样就能建立连接发送数据了。

一、《JAY》2000年11月01日
01.可爱女人 … 词:徐若宣 曲:周杰伦 编:周杰伦
02.完美主义 … 词:方文山 曲:周杰伦 编:洪敬尧
03.星晴 ……. 词:周杰伦 曲:周杰伦 编:洪敬尧
04.娘子 ……. 词:方文山 曲:周杰伦 编:周杰伦
05.斗牛 ……. 词:方文山 曲:周杰伦 编:洪敬尧
06.黑色幽默 … 词:周杰伦 曲:周杰伦 编:洪敬尧
07.伊斯坦堡 … 词:徐若宣 曲:周杰伦 编:洪敬尧
08.印地安老斑鸠 词:方文山 曲:周杰伦 编:洪敬尧
09.龙卷风 ….. 词:徐若宣 曲:周杰伦 编:钟兴民
10.反方向的钟 . 词:方文山 曲:周杰伦 编:周杰伦

二、《FANTASY》2001年09月18日
01.爱在西元前 . 词:方文山 曲:周杰伦 编:林迈可
02.爸我回来了 . 词:周杰伦 曲:周杰伦 编:钟兴民
03.简单爱 ….. 词:徐若宣 曲:周杰伦 编:林迈可
04.忍者 ……. 词:方文山 曲:周杰伦 编:林迈可
05.开不了口 … 词:徐若宣 曲:周杰伦 编:洪敬尧
06.上海一九四三 词:方文山 曲:周杰伦 编:林迈可
07.对不起 ….. 词:方文山 曲:周杰伦 编:洪敬尧
08.威廉古堡 … 词:方文山 曲:周杰伦 编:洪敬尧
09.双截棍 ….. 词:方文山 曲:周杰伦 编:钟兴民
10.安静 ……. 词:周杰伦 曲:周杰伦 编:钟兴民

三、《八度空间》2002年07月19日
1.半兽人 …… 词:方文山 曲:周杰伦 编:林迈可
2.半岛铁盒 …. 词:周杰伦 曲:周杰伦 编:林迈可
3.暗号 …….. 词:许世昌 曲:周杰伦 编:林迈可
4.龙拳 …….. 词:方文山 曲:周杰伦 编:洪敬尧
5.火车叨位去 .. 词:方文山 曲:周杰伦 编:洪敬尧
6.分裂 …….. 词:周杰伦 曲:周杰伦 编:钟兴民
7.爷爷泡的茶 .. 词:方文山 曲:周杰伦 编:林迈可
8.回到过去 …. 词:刘耕宏 曲:周杰伦 编:林迈可
9.米兰的小铁匠 词:方文山 曲:周杰伦 编:洪敬尧
10.最后的战役 . 词:方文山 曲:周杰伦 编:钟兴民

四、《叶惠美》2003年07月31日
01 以父之名 … 词:黄俊郎 曲:周杰伦 编:洪敬尧
02 懦夫 ……. 词:周杰伦 曲:周杰伦 编:周杰伦
03 晴天 ……. 词:周杰伦 曲:周杰伦 编:周杰伦
04 三年二班 … 词:方文山 曲:周杰伦 编:洪敬尧
05 东风破 ….. 词:方文山 曲:周杰伦 编:林迈可
06 你听得到 … 词:曾郁婷 曲:周杰伦 编:林迈可
07 同一种调调 . 词:方文山 曲:周杰伦 编:钟兴民
08 她的睫毛 … 词:方文山 曲:周杰伦 编:周杰伦
09 爱情悬崖 … 词:徐若瑄 曲:周杰伦 编:钟兴民
10 梯田 ……. 词:周杰伦 曲:周杰伦 编:周杰伦
11 双刀 ……. 词:方文山 曲:周杰伦 编:钟兴民

五、《七里香》2004年08月03日
1.我的地盘 …. 词:方文山 曲:周杰伦 编:洪敬尧
2.七里香 …… 词:方文山 曲:周杰伦 编:钟兴民
3.借口 …….. 词:周杰伦 曲:周杰伦 编:周杰伦
4.外婆 …….. 词:周杰伦 曲:周杰伦 编:周杰伦
5.将军 …….. 词:黄俊郎 曲:周杰伦 编:洪敬尧
6.搁浅 …….. 词:宋健彰 曲:周杰伦 编:钟兴民
7.乱舞春秋 …. 词:方文山 曲:周杰伦 编:钟兴民
8.困兽之斗 …. 词:刘畊宏 曲:周杰伦 编:蔡科俊
9.园游会 …… 词:方文山 曲:周杰伦 编:洪敬尧
10.止战之殇 … 词:方文山 曲:周杰伦 编:周杰伦

六、《十一月的萧邦》2005年11月01日
1 夜曲 ……. 词:方文山 曲:周杰伦 编:林迈可
2 蓝色风暴 … 词:方文山 曲:周杰伦 编:洪敬尧
3 发如雪 ….. 词:方文山 曲:周杰伦 编:林迈可
4 黑色毛衣 … 词:周杰伦 曲:周杰伦 编:林迈可
5 四面楚歌 … 词:周杰伦 曲:周杰伦 编:洪敬尧
6 枫 ……… 词:宋健彰 曲:周杰伦 编:钟兴民
7 浪漫手机 … 词:方文山 曲:周杰伦 编:洪敬尧
8 逆鳞 ……. 词:黄俊郎 曲:周杰伦 编:钟兴民
9 麦芽糖 ….. 词:方文山 曲:周杰伦 编:洪敬尧
10 珊瑚海 …. 词:方文山 曲:周杰伦 编:钟兴民

七、《依然范特西》2006年9月5日
01 夜的第七章………词:黄俊郎 曲:周杰伦 编:钟兴民、林迈可
02 听妈妈的话………词:周杰伦 曲:周杰伦 编:林迈可、洪敬尧
03 千里之外(周杰伦/费玉清)…词:方文山 曲:周杰伦编:林迈可
04 本草纲目……………………词:方文山 曲:周杰伦 编:林迈可
05 退后…………………………词:宋健彰 曲:周杰伦 编:林迈可
06 红模仿………………………词:周杰伦 曲:周杰伦 编:林迈可
07 心雨…………………………词:方文山 曲:周杰伦 编:林迈可
08 白色风车……………………词:周杰伦 曲:周杰伦 编:蔡科俊
09 迷迭香………………………词:方文山 曲:周杰伦 编:钟兴民
10 菊花台………………………词:方文山 曲:周杰伦 编:钟兴民

八、《我很忙》2007年11月01日
01.牛仔很忙 词:黄俊郎 曲:周杰伦 编:钟兴民
02.彩虹 词:周杰伦 曲:周杰伦 编:林迈可
03.青花瓷 词:方文山 曲:周杰伦 编:钟兴民
04.阳光宅男 词:方文山 曲:周杰伦 编:周杰伦
05.蒲公英的约定 词:方文山 曲:周杰伦 编:林迈可
06.无双 词:方文山 曲:周杰伦 编:钟兴民
07.我不配 词:方文山 曲:周杰伦 编:林迈可
08.扯 词:方文山 曲:周杰伦 编:林迈可
09.甜甜的 词:方文山 曲:周杰伦 编:林迈可
10.最长的电影 词:周杰伦 曲:周杰伦 编:钟兴民

九、《魔杰座》2008年10月15日
01.龙战骑士 …………词:方文山 曲:周杰伦 编:钟兴民
02.给我一首歌的时间 词:周杰伦 曲:周杰伦 编:林迈可
03.蛇舞 ………………词:黄俊郎 曲:周杰伦 编:黄雨勋
04.花海 ………………词:古小力、黄凌嘉 曲:周杰伦 编:黄雨勋
05.魔术先生 …………词:方文山 曲:周杰伦 编:钟兴民
06.说好的幸福呢 ……词:方文山 曲:周杰伦 编:钟兴民
07.兰亭序 ……………词:方文山 曲:周杰伦 编:钟兴民
08.流浪诗人………… 词:方文山 曲:周杰伦 编:蔡科俊
09.时光机 ……………词:方文山 曲:周杰伦 编:黄雨勋
10.乔克叔叔 …………词:黄俊郎 曲:周杰伦 编:黄雨勋
11.稻香 ………………词:周杰伦 曲:周杰伦 编:黄雨勋

十、《跨时代》2010年5月18日
01.跨时代 …………词:黄俊郎 曲:周杰伦 编:黄雨勋
02.说了再见……… 词:古小力、黄淩嘉 曲:周杰伦 编:钟兴民
03.烟花易冷 ………词:方文山 曲:周杰伦 编:黄雨勋
04.免费教学录影带 词:黄俊郎 曲:周杰伦 编:蔡科俊
05.好久不见 ………词:周杰伦 曲:周杰伦 编:蔡庭贵
06.雨下一整晚 ……词:方文山 曲:周杰伦 编:钟兴民
07.嘻哈空姐 ………词:方文山 曲:周杰伦 编:林迈可
08.我落泪情绪零碎 词:方文山 曲:周杰伦 编:钟兴民
09.爱的飞行日记 …词:方文山 曲:周杰伦 编:蔡科俊
10.自导自演 ………词:周杰伦 曲:周杰伦 编:黄雨勋
11.超人不会飞…… 词:周杰伦 曲:周杰伦 编:林迈可

十一 《惊叹号》 2011.11.11
1.惊叹号…………(词:方文山 曲:周杰伦 编曲:林迈可)
2.迷魂曲…………(词:方文山 曲:周杰伦 编曲:林迈可)
3.MineMine………(词:周杰伦 曲:周杰伦 编曲:林迈可)
4.公主病…………(词:周杰伦 曲:周杰伦 编曲:黄雨勋)
5.你好吗…………(词:罗玉轩/李汪哲 曲:周杰伦 编曲:黄雨勋)
6.疗伤烧肉粽……(词:周杰伦 曲:周杰伦 编曲:林迈可)
7.琴伤……………(词:方文山 曲:周杰伦 编曲:黄雨勋)
8.水手怕水………(词:黄俊郎 曲:周杰伦 编曲:周杰伦)
9.世界未末日……(词:方文山 曲:周杰伦 编曲:林迈可)
10.皮影戏 ………(词:唐从圣 曲:周杰伦 编曲:林迈可)
11.超跑女神………(词:方文山 曲:周杰伦 编曲:林迈可)

十二 《十二新作》 2012.12.28
01.四季列车……………(词:方文山/曲:周杰伦/编曲:周杰伦)
02.手语…………………(词:周杰伦/曲:周杰伦/编曲:林迈可)
03.公公偏头痛…………(词:方文山/曲:周杰伦/编曲:周杰伦)
04.明明就………………(词:方文山/曲:周杰伦/编曲:黄雨勋)
05.傻笑…………………(词:方文山/曲:周杰伦/编曲:黄雨勋)
06.比较大的大提琴……(词:方文山/曲:周杰伦/编曲:黄雨勋)
07.爱你没差……………(词:黄凌嘉/曲:周杰伦/编曲:黄雨勋)
08.红尘客栈……………(词:方文山/曲:周杰伦/编曲:黄雨勋)
09.梦想启动……………(词:林义杰/曲:周杰伦/编曲:林迈可)
10.大笨钟………………(词:周杰伦/曲:周杰伦/编曲:黄雨勋)
11.哪里都是你…………(词:周杰伦/曲:周杰伦/编曲:黄雨勋)
12.乌克丽丽……………(词:周杰伦/曲:周杰伦/编曲:林迈可)

十三、《诶哟,不错哦!》 2014.12.26
01.阳明山………………词:方文山/曲:周杰伦/编曲:林迈可
02.窃爱……… ……… 词:黄俊郎/曲:周杰伦/编曲:黄雨勋/梦想之翼
03.算什么男人…………词:周杰伦/曲:周杰伦/编曲:黄雨勋/梦想之翼
04.天涯过客……………词:方文山/曲:周杰伦/编曲:黄雨勋/梦想之翼
05.怎么了………………词:方文山/曲:周杰伦(女声:袁咏琳)/编曲:林迈可
06.一口气全念对………词:方文山/曲:周杰伦/编曲:周杰伦
07.我要夏天……………词:周杰伦/曲:周杰伦/编曲:黄雨勋/梦想之翼
08.手写的从前…………词:方文山/曲:周杰伦/编曲:黄雨勋/梦想之翼
09.鞋子特大号…………词:方文山/曲:周杰伦/编曲:黄雨勋/梦想之翼
10.听爸爸的话…………词:周杰伦/曲:周杰伦/编曲:黄雨勋/梦想之翼
11.美人鱼………………词:罗宇轩 Josh Lo. 黄婕熙/曲:周杰伦/编曲:黄雨勋/梦想之翼
12.听见下雨的声音……词:方文山/曲:周杰伦/编曲:黄雨勋/梦想之翼

周六去香山拉练LSD,三爬香山,共计路线是从静翠湖开始,沿着南香山墙至香炉峰,绕圈下至静翠湖。沿路一直听见有人说还是下山容易,不怎么冒汗。刚好本次爬山带有佳明飞耐时2和心率带,就用数据揭示下爬山和下山的难度,喘气,冒汗等各种现象。
下图是总览图,包括路线,心率,海拔。
1、路线。
静翠湖开始,沿着南香山墙至香炉峰,绕圈下至静翠湖。三圈,耗时5.5小时。

2、海拔
香山海拔高度是550米,起始海拔是120,所以落差是430米。累计爬升1400米,累计下降1400米(累计的数量包括山岭的起伏也计算在内)。

3、心率。
第一圈,上山:平均150次/分。下山:平均110次/分
第二圈,上山:平均155次/分。下山:平均120次/分
第三圈,上山:平均160次/分。下山:平均125次/分

5、速度。
第一圈,上山:3公里/小时。下山:5公里/小时。
第二圈,上山:3公里/小时。下山:5公里/小时。
第三圈,上山:3公里/小时。下山:6公里/小时。

总结。
1、上山心率155次/分,下山心率120次。
这是个什么概念呢?与其他运动方式比较:慢跑的心率150次/分。快走的心率是130次/分。
2、为何慢跑不累,上山很累。
慢跑克服的是横向的摩擦力,计算公式为f =μN ,μ叫滑动摩擦系数,它只跟材料、接触面粗糙程度有关;N为正压力,即体重。爬山克服的是重力,即N。相同的十分钟里,相同功率的输出下,爬山感觉要更费力些,特别是大腿部分。
3、为何下山很很很轻松
下山,基本不需要克服很多力量,只要腿部的支撑。
4、为何几个台阶一个小平台的山的比较容易爬上去,而无休息平台的比较难爬。
由于在在平台(跟走路差不多)处处于克服摩擦力,消耗较小,心率会降下来(参考120次/分),所以轻松;而无休息平台的一直处于克服重力(一直在爬坡),消耗较大,心率激增(参考155次/分),如果持续攀登,最高飙升至170次/分,此时心脏处于高负荷状态,比较危险,所以提倡慢爬,稳爬。
5、上山容易?
错。上山一点都不容易。上山高负荷,会感到呼吸急促,大量出汗,心率飙升。
6、下山难?
错。下山一点也不难。下山心率较低,较为轻松,基本不出汗。
7、为何说“上山容易,下山难”
上山后大量消耗体能,腿会酸软,而下山时速度比上山较快,体乏腿酸,重心不好控制,较危险。所以应该说“上山累人,下山危险”较为准确。

双向链表的特点:
1、以节点为单位,每个节点有上个节点指针和下个节点指针
2、至少包含头节点和尾节点
3、添加节点时先改变新增节点的上下节点指针指向,后修改前后节点的指针指向为当前节点
4、删除节点时修改当前节点的前后节点指向,然后删除当前节点
5、迭代器用来封装节点数据,并提供了操作符的能力,如*,++,==,!=
6、列表的操作有:取头,取尾,删头,删尾,删指定位置,加头,加尾,加指定位置

template
class List
{
private:

struct Node
{
    Object data;
    Node *prev;
    Node *next;

    Node(const Object &d = Object(), Node *p = NULL, Node *n = NULL)
        : data(d), prev(p), next(n)
    {

    }
};

public:

class const_iterator
{
public:
    const_iterator() : current(NULL)
    {

    }

    const Object &operator* () const
    {
        return retrieve();
    }

    const_iterator & operator++ ()
    {
        current = current->next;
        return *this;
    }

    const_iterator operator++ (int)
    {
        const_iterator old = *this;
        ++(*this);
        return old;
    }

    bool operator == (const const_iterator &rhs) const
    {
        return current == rhs.current;
    }

    bool operator != (const const_iterator &rhs) const
    {
        return !(*this == rhs);
    }

protected:
    Node *current;
    Object &retrieve() const
    {
        return current->data;
    }
    const_iterator(Node *p) : current(p)
    {

    }

    friend class List < Object >;
};

class iterator : public const_iterator
{
public:
    iterator()
    {

    }

    Object & operator* ()
    {
        return retrieve();
    }

    iterator &operator++()
    {
        current = current->next;
        return *this;
    }

    iterator operator++ (int)
    {
        iterator old = *this;
        ++(*this);
        return old;
    }

protected:
    iterator(Node *p) : const_iterator(p)
    {

    }

    friend class List < Object >;
};

public:

List()
{
    init();
}
~List()
{
    clear();
    delete head;
    delete tail;
}
List(const List &rhs)
{
    init();
    *this = rhs;
}

const List &operator = (const List &rhs)
{
    if (this == &rhs)
    {
        return *this;
    }
    clear();
    for (const_iterator itr = rhs.begin(); itr != rhs.end(); ++itr)
    {
        push_back(*itr);
    }

    return *this;
}

iterator begin()
{
    return iterator(head->next);
}

const_iterator begin() const
{
    return const_iterator(head->next);
}

iterator end()
{
    return iterator(tail);
}

const_iterator end() const
{
    return const_iterator(tail);
}

int size() const
{
    return theSize;
}
bool empty() const
{
    return size() == 0;
}

void clear()
{
    while (!empty())
        pop_front();
}

Object &front()
{
    return *begin();
}

const Object & front() const
{
    return *begin();
}
Object &back()
{
    return *--end();
}
const Object &back() const
{
    return *--end();
}
void push_front(const Object &x)
{
    insert(begin(), x);
}
void push_back(const Object &x)
{
    insert(end(), x);
}
void pop_front()
{
    erase(begin());
}
void pop_back()
{
    erase(--end());
}

iterator insert(iterator itr, const Object &x)
{
    Node *p = itr.current;
    theSize++;
    return iterator(p->prev = p->prev->next = new Node(x, p->prev, p));
}
iterator erase(iterator itr)
{
    Node *p = itr.current;
    iterator retVal(p->next);
    p->prev->next = p->next;
    p->next->prev = p->prev;
    delete p;
    theSize--;

    return retVal;
}

iterator erase(iterator start, iterator end)
{
    for (iterator itr = start; itr != end;)
    {
        itr = erase(itr);
    }

    return end;
}

private:

int theSize;
Node *head;
Node *tail;
void init()
{
    theSize = 0;
    head = new Node;
    tail = new Node;
    head->next = tail;
    tail->prev = head;
}

};

int main()
{

List<int> nList;
nList.push_back(1);
nList.push_back(2);
nList.push_back(3);
nList.push_back(4);
for (List<int>::const_iterator itr = nList.begin(); itr != nList.end(); itr++)
{
    LOG_INFO("itr vaule:" << *itr);
}

//
for (List<int>::iterator itr = nList.begin(); itr != nList.end(); )
{
    nList.erase(itr++);
}

LOG_INFO("List size:" << nList.size());
reutrn 0;

}

二分搜索法特点:
1、数据顺序排列
2、每次去取最中间的数值
3、根据目标数和中间数的大小,调整最小值索引或最大值索引范围
4、直至匹配或者无法继续3的操作

template;
int BinarySearch(const std::vector &nVector, const CompareData &nData)
{

int nLow = 0;
int nHigh = nVector.size() - 1;
while (nLow &lt;= nHigh)
{
    int nMid = (nLow + nHigh) / 2;

    if (nVector[nMid] &lt; nData)
    {
        nLow = nMid + 1;
    }
    else if (nVector[nMid] &gt; nData)
    {
        nHigh = nMid - 1;
    }
    else
    {
        return nMid + 1;
    }
}

return -1;

}

int main()
{

std::vector<int> nVector;
for (int i = 0; i < 10; i++)
{
    nVector.push_back(i);
}

int result = BinarySearch(nVector, 5);
LOG_INFO("result:" << result);

}