【时间管理美高梅娱乐4858.com】时间管理从设置休息时间发轫

时间管理从设置休息时间初阶

引言

在时刻管理课上,有一句话让作者极度不容忽视,永锡老师说,时间管理要先安装休息的时辰。笔者每日都会每一日检验自个儿的行动清单,那张清单上唯有一个是与休息相关的,那就是十二分钟的冥想时间,而每一遍做完那10秒钟的冥思苦想将来,作者都会有一种非凡清爽的觉得,但为什么小编一天唯有10分钟用在那件让祥和感觉优良的政工上啊?

  <<独白>> 席慕蓉 节选一

精心查看后发现,原来自家的年月观重假若一种缺少的概念,作者总会认为时间是不够用的,内心会有焦虑的情怀,以后的小编会不断裁减本人休息的时刻,而过去的自小编,则喜欢用熬夜、一心多用的点子来掩盖本身对此时间流逝的焦虑感。

美高梅娱乐4858.com 1  

近期几天因为要做马拉松陶冶,身体的疲劳度大增,不得不伸张了汪洋的不久休息时间,以恢复生机和谐的生气值,结果自个儿的工作功效却反而大幅升高,尤其是考虑的活跃度,鲜明上涨了三个等级,许多原先看不懂的东西将来大约是直觉式的直接可以感应到,根本不要求费力去思维。也就认证了永锡老师所说,时间管理应当从设置休息时间伊始。

       把向您借来的笔还给你吗。

一 、什么是休息?

本身给休息的定义是:

过来体力、脑力,同时过来心理的位移。

有的是常识中觉得是休息的移位只是一种注意力的转换,比如看录像、TV,那是因此让大脑中接收音讯部分工作,从而让大脑中负责思考的有的停止工作,所以一旦脑残电视机剧看多了,那真的会变笨的。那种移动固然让思维部分的大脑得到按兵不动,但大脑的完全并不曾得到上升,看完剧未来一样很劳碌,白白浪费时间。

如同的位移包括:逛街、购物、社交、打鸡血。

不畏你觉得自个儿一天到晚到很闲,但您或许照样缺乏休息,比如从早到晚打网游、逛天猫,那实在是很累的,而且你如此做和喝酒是同等,是一种采纳成瘾行为拒绝休息的形式,因为真正的恢复生机会让你静下来,而若是静下来,你才真的办好准备去思维。

判断你到底是休息或然转移注意力卓殊简单,做完一轮活动后,你拿起一本韩语单词书,开端背,即便3分钟后你曾经快要睡着了,那就只是转移注意力而已。特别要留意的是,若是一项运动会让您的感情小幅波动,这些运动必将会开支而非补充你的生气。

确实的按兵不动活动实际不多,也很粗略:
NO1——睡觉
NO2——发呆
NO3——有氧运动

前双方不用多解释,就是纯粹让大脑安静下来,而有氧运动比如长跑,做过的人都会精晓,当你活动丰硕长的日子后,大脑会赢得丰富的宁静,就是我们常说的放空大脑,实际上催眠、冥想、瑜伽等等都有像样的作用,只不是那一个有点难,不像跑步没人教导也同等能进入这种情形,只是切记跑步的时候别听音乐,因为跑步听音乐其实又是一种对时间的紧缺感,结果造成跑步也化为了一种消耗。

 

二 、多久休息三次

每60分钟至少休息三次。

有的是程序员、设计师之类的人,一旦进入工作状态就会不停的工作,不累死不休息。那一点一滴是小朋友贪玩的习惯带到了大人的世界,你有见过哪些NBA球员是全场竞技里一分钟都不休息的啊,别说什么脑子活动和体力活动不一样,爱因Stan也以日常打盹休息著称,就连时间管理界的圣人《奇特的终生》的中坚,柳比歇夫,也是一天睡10多少个钟头,平常休息的主。直接确认吗,你不肯休息不外如此多少个原因:

  • 您是个办事狂

  • 你喜欢在办事情状那种痛感,你毛骨悚然一旦退出就再回不去了

  • 你平素就不懂什么保持持续的干活情状

再强调三遍,找个倒计时器,开头操练番茄工作法吧,休息是为着走的更远,别把团结当机器。

       一切都发生在回看的须臾间。

③ 、投资投机的肉身

作者不是体能练习,也不是营养师,但自身的亲自体会告诉本身,当本身天天跑1钟头的长跑将来,小编每一天能增添3时辰的高精力值状态,工作的结晶能扩张一倍。当本身关注餐饮,少吃多餐时,作者的沉思活跃就会做实,领悟力和血汗的持久度都会狠抓。

唯独,这一切都是有代价的。

在小编刚开首跑步的时候,天天要多睡2时辰,约等于一天要睡差不离9-10钟头,直到3个月后,作者才过来到7小时的睡觉时间。作者刚早先转移饮食结构时,每一日都会没完没了想来一口可乐,经过M记时薯条的花香直接会引的口水直流,但现行我相对不用再从70KG变回这一个90KG的自作者了。那一个似乎投资一样,总是要先投入才有回报。

给协调每时辰布置5-10分钟的休养,什么也不做,什么也不想,只是静静地和融洽在协同,感觉一下肉体的依次部分,感觉一下心理在身上的流动,然后您就坚实了预备,对协调负担了。


 

文章版权消息

     
小编的彻悟尽管是缘自一种迷乱,那么,作者的各种迷乱不也就只是因为一种彻悟?

 

     
在五次忆间,才恍然发现,原来,小编的毕生的种种努力,但是只是为了周遭的人都对自小编满意而已。

为了要取得别人的表彰与微笑,小编恐惧地将团结套入全部的情势,全体的管束。

走到中途,才突然发现,我只剩余一副模糊的精神,和一条不只怕悔过自新的路。

 

     把向你借来的笔还给您啊。

 

配乐 :

  我在长大 : http://music.163.com/#/song?id=155977

不知疲倦的整夜码代码 像块石头同样滚来滚去
可是找不到家的倾向
自己在长大 / 小编在长大 / 作者在长大 / 作者在长大

 

前言

大家先说一下,参照的事物和必要明白的东西

现实参照

  1. HTTP商事简单介绍
http://www.cnblogs.com/biyeymyhjob/archive/2012/07/28/2612910.html

此处须求控制不难的Linux 操作,那里享受三个投机总计的socket入门基础文档.

    2. socket 不难入门doc
http://download.csdn.net/detail/wangzhione/9412538

到那边, 基本准备工作就形成了,那就搞起啊, 看看那多少个说起来很神秘的工具是怎么归纳落成的.顺带扯一点,

上边代码自身多看三遍写四遍,可以扶持你明白Linux中有的是基础概念,例如 信号,多进度, 管道,socket,中断,

协议等.

 

正文

1.简便说一点格式

  这里大家先看下边一段代码格式,来询问C接口设计中有的不成文规则.

/*
 * 这是一个对外的接口函数声明,
 *相当于public
 */
extern int isbig(void);

/*
 * 这个接口也具备对外能力,但是省略了extern
 *意图就是构建整个 *.h文件的时候需要用它,但是不希望用户用.
 *属于 low level api, 内部接口集用,外部不推荐用,有点像protected
 */
int heoo(void);

/*
 *    这个是个内部声明或定义, 只能在当前接口集的内部使用,外部无法
 *访问,相当于pirate
 */
static void* __run(void* arg);

概念部分简单说圣元(Synutra)(Beingmate)下.之前博文中说过,那里再不难说三回,编程和打游戏一样,要有好点子,

要有好套路,那样打起来才顺.等同于实践可以统计出理论基础.前任要感激.

/*
 * 定义加声明,放在一块
 */
static int __run(void)
{
    static union {
        unsigned short _s;
        unsigned char _cs[sizeof(unsigned short)];
    } __ut = { 1 };
    return __ut._cs[0] == 0;
}

/*
 * 声明和定义分开
 */
 extern void start(void);
 //下面是定义部分
 void
 start(void)
 {
     puts("你好!");
 }

套路很多,都以历代编程王者,开创的各大武术的起手式,各大定式都得以就看您想拜入那么些门派,发轫那么些编程网游之旅.

 

2.说思路

  经过地点简单格式介绍,那里就说一下思路. 关于 那篇博文,C 对网页的下压力测试打造的思路.具体如下:

a. 拼接请求报文 , 解析

b. 发送请求报文 , 请求

c. 处理请求报文, 处理

d.计算请求报文, 输出计算

地点就是这一次拍卖的要害流程, 多次伸手采用的fork多少个子进度

    for(i=0; i<cut; ++i){
        pid = fork(); //狂开进程了
        if(pid <= 0){
            sleep(1);//别让它太快完毕,父进程来不及收尸
            break;//结束子进程继续
        }
        ++rt;
    }        

至于父子进度通讯接纳 管道

    //创建管道 进行测试, 代码比较杂,需要一些Linux基础知识,多练习
    if(pipe(pfds)<-1)
        CERR_EXIT("pipe create is error!");

再有2个是因而信号处理超时难点

//默认全局标识, 控制开关
volatile int v_timer = 0;

//闹钟信号,当它启动那一刻就表示可以退下了.
static void __alarm(int sig)
{
    v_timer = 1;
}

末端大家就由此代码来说了,最好您写几次,就领会简单了.扯一点,关于volatile 可以表明是为了艺术编译器优化,导致代码死循环.

 

3.各种落到实处

第①部分头文件,评释解析

首先寓目上边前戏代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//控制台打印错误信息, fmt必须是双引号括起来的宏
#ifndef CERR
#define CERR(fmt, ...) \
    fprintf(stderr,"[%s:%s:%d][error %d:%s]" fmt "\r\n",\
         __FILE__, __func__, __LINE__, errno, strerror(errno),##__VA_ARGS__)

//检测并退出的宏
#define CERR_EXIT(fmt, ...) \
    CERR(fmt, ##__VA_ARGS__), exit(EXIT_FAILURE)

#endif/* !CERR */

// url长度限制 和 请求串长度限制
#define _INT_URL (1024)
#define _INT_REQ (2048)
//主机地址的最大长度
#define _INT_PORT (255)
//等待时间,在60s后就不在处理了
#define _INT_END  (23)

//简单结构
struct iport{
    short port;
    char ip[_INT_PORT];
};

//默认全局标识, 控制开关
volatile int v_timer = 0;

//闹钟信号,当它启动那一刻就表示可以退下了.
static void __alarm(int sig)
{
    v_timer = 1;
}

/*
 * 执行的主要方法,结果会通过写管道 wfd写入
 */
void bcore(struct iport* ips, const char* req, int wfd);

/*
 * 只接受完整请求 
 * 例如
 * brequest("http://192.168.1.162:80/", ...) 或 http://www.baidu,com
 * 通过url拼接请求串,并返回访问结构
 */
struct iport* brequst(const char* url, char rqs[], int len);
//请求主方法,客户端,返回开启的子进程数
int bench(int cut, const char* url, int wfd);

/*
 * 请求链接主机,根据ip或url
 *
 * host    : url地址
 * port : 请求的端口号
 */
int contweb(const char* host, int port);

CE帕杰罗帕杰罗连串是一个帮助宏,简单打印错误消息. 技巧值得推荐使用.其中
_INT_END 代表各个子进程请求的时辰长度(s).

倍感注释也挺详细的有关

//请求主方法,客户端,返回开启的子进程数
int bench(int cut, const char* url, int wfd);

首要开启多进程的,依次调用 breques解析url 和 调用 bcore 处理socket
.

内部 contweb 是1个足以按照ip或主机地址url解析,链接主机.具体已毕如下

/*
 * 请求链接主机,根据ip或url
 *
 * host    : url地址
 * port : 请求的端口号
 */
int 
contweb(const char* host, int port)
{
    int sd;
    in_addr_t ia;
    struct sockaddr_in sa = { AF_INET };    
    struct hostent *hp;

    ia = inet_addr(host);
    if(ia != INADDR_NONE)
        memcpy(&sa.sin_addr, &ia, sizeof(ia));
    else {
        hp = gethostbyname(host);
        if(hp < 0){
            CERR("gethostbyname %s error!", host);
            return -1;
        }
        memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);    
    }
    if((sd=socket(PF_INET, SOCK_STREAM, 0))<0){
        CERR("socket SOCK_STREAM");
        return sd;
    }    

    //连接主机
    sa.sin_port = htons(port);
    if(connect(sd, (struct sockaddr*)&sa, sizeof sa)<0){
        CERR("connect sd:%d error!", sd);
        return -1;
    }

    return sd;    
}

从不什么花哨的事物就是一起链接HTTP服务器, 即使传入的的host是url那么就调用 gethostbyname 获取到 请求

主机的sin_addr地址量.

扯一点,socket编程一大半也一如既往业务代码,固定的覆辙固定的方式,写写也都会写了.但也挺费劲了,随便一个粗略的

一体化的socket demo都4-5百行代码,写的手疼.封装也很麻烦.可是您通晓了它的笔触或套路,照旧很不难上马提枪的.

 

其次部分逐项,定义解析

  首先代码可以优化,小编写好后没优化了,就一贯分享了.先看http协议分析代码如下

//通过url拼接请求串
struct iport* 
brequst(const char* url, char rqs[], int len)
{
    static struct iport __ips;
    //请求的主机, 中间用的url, 临时数据
    const char *hurl, *tmp;        
    char c;
    int pt = 0;//临时用的int变量

    //简单检查参数检查,检查数组大小,url是否合法
    if(len<_INT_REQ || !url || !*url || strlen(url)>_INT_URL)
        CERR_EXIT("params url:%s, len[>=%d];%d error.", url, _INT_REQ, len);    
    //检测url是否是http请求的url,也比较简单,复杂检查要用正则表达式
    hurl = strstr(url, "://");
    if(!hurl || strncasecmp(url, "http", 4))
        CERR_EXIT("url is err [%s]!", url);
    //简单初始化
    memset(rqs, 0, len);    
    memset(&__ips, 0, sizeof __ips);

    //这种代码可以优化,用指针替代数组索引
    strcat(rqs, "GET ");
    hurl += 3; //跳过 "://"指向下一个字符

    //解析url 上是否有端口信息
    tmp = index(hurl, ':');
    if(tmp && tmp < index(hurl, '/')){ 
        strncpy(__ips.ip, hurl, tmp - hurl);
        //没有做安全检查
        while((c=*++tmp)!='\0' && c!='/'){
            if(c<='9' && c>='0'){
                pt = 10*pt + c - '0';
                continue;
            }
            CERR_EXIT("url is error [%s].", url);        
        }
    }    
    else{
        pt = 80; //默认端口
        //这句话意思 是 将 www.baidu.com/ 其中/之前的地方写入到 ip[]中
        strncpy(__ips.ip, hurl, strcspn(hurl, "/"));    
    }
    __ips.port = pt;    

    //将这些内容链接到rqs中
    strcat(rqs, hurl + strcspn(hurl, "/"));
    //采用HTTP1.1 协议
    strcat(rqs, " HTTP/1.1\r\n");
    //添加请求方
    strcat(rqs, "User-Agent: Happy is good.\r\n");
    //上面这样解析有点慢,最快的是整体for,但是更难维护
    strcat(rqs, "Host: ");
    strcat(rqs, __ips.ip);
    strcat(rqs, "\r\n");
    //拼接串最后,连接状态,完毕就关闭
    strcat(rqs, "Connection: close\r\n");
    //拼接空行, 上面可以优化
    strcat(rqs, "\r\n");

    //最终检测,是否字符串太长了
    if(rqs[len-1])
        CERR_EXIT("get http too len!");

    return &__ips;            
}

第三思路是先检查 参数, 看 是或不是是 左侧那样正则格式的串 
“http.://.+/”

后边拼接结果截图如下:

美高梅娱乐4858.com 2

愈来愈详实关于HTTP协议分析的,可以参见笔者前边的三番五次,HTTP协议不难解析.

末尾介绍的是有了请求串,怎么发送请求和处理请求,代码如下:

/*
 * 执行的主要方法,结果会通过写管道 wfd写入
 */
void 
bcore(struct iport* ips, const char* req, int wfd)
{
    int srv, len, rlen;
    int speed = 0, failed = 0, bytes = 0;
    FILE* fx;
    char buf[_INT_REQ];    

    //先注册信号
    if(SIG_ERR == signal(SIGALRM, __alarm))
        CERR_EXIT("signal SIGALRM error!");
    alarm(_INT_END);

    len = strlen(req);    
    for(;;){
        if(v_timer){ //结束之前减一,认为成功过
            if(failed>0)
                --failed;
            break;
        }        

        srv = contweb(ips->ip, ips->port);
        if(srv < 0){
            ++failed;
            continue;    
        }
        //开始写入数据
        if(len != write(srv, req, len)){
            ++failed;
            close(srv);
            continue;
        }
        //下面读取数据,v_timer标志是否超时,超时直接走
        for(;!v_timer;){
            rlen = read(srv, buf, _INT_REQ);                
            if(rlen < 0){ //不考虑软中断了,有问题直接退出
                ++failed;
                close(srv);
                goto __bcore_exit; //退出结算
            }
            if(rlen == 0)//服务端关闭,结束读取
                break;
            bytes += rlen;
        }
        close(srv);
        ++speed;
    }    

__bcore_exit:
    //管道写入
    fx = fdopen(wfd, "w");
    if(NULL == fx)    
        CERR_EXIT("fdopen wfd:%d error!", wfd);
    fprintf(fx,"%d %d %d\n", speed, failed, bytes);    
    fclose(fx);
}

高中级发送了三个alarm延时发送SIGAL逍客M 信号,还有3个信号简单混淆视听,是SIGCLD信号 子进度退出时候给父进度发送.

里头 fdopen 是将 Linux文件讲述符和 C系统文件操作句柄转换.就是计算数据写入到管道中,管道 是
1进 0出.

最后还有个 开启多进程的函数代码

//请求主方法,客户端,返回开启子进程数
int 
bench(int cut, const char* url, int wfd)
{
    int i, rt = 0;//rt 记录正常开启的进程
    pid_t pid;
    char req[_INT_REQ];
    struct iport* ips;

    //这里初始化一些环境
    ips = brequst(url, req, sizeof req);    
    puts("***********-----------------------------------------------------------***********");
    puts(req); //打印数据
    puts("***********-----------------------------------------------------------***********");

    for(i=0; i<cut; ++i){
        pid = fork(); //狂开进程了
        if(pid <= 0){
            sleep(1);//别让它太快完毕,父进程来不及收尸
            break;//结束子进程继续
        }
        ++rt;
    }        
    if(pid < 0)
        CERR_EXIT("child %d process create error!", i);
    if(pid == 0){ //子进程处理
        bcore(ips, req, wfd);
        exit(EXIT_SUCCESS);//子进程这里就结束了
    }
    //下面是父进程处理
    return rt;                    
}

也正如好了然,先凑合请求串,再打开多进度挨个请求处理.

到那基本函数基本都成功了,总的业务创设请看上面

 

其三有的主函数逻辑创设

// 主函数业务,从这开始
int main(int argc, char* argv[])
{
    int cut, len; //开启进程数量 和 读取scanf返回值
    int pfds[2];    
    FILE* fx;
    int speed = 0, failed = 0, bytes = 0;

    //简单检测    
    if((argc != 3) || (cut = atoi(argv[1]))<=0 || cut > USHRT_MAX){        
        CERR_EXIT(
             "\r\nuage:   ./webtest.out [cut] [url]"
            "\r\n    :=> ./webtest.out 19 http://www.baidu.com/"
        );
    }    

    //创建管道 进行测试, 代码比较杂,需要一些Linux基础知识,多练习
    if(pipe(pfds)<-1)
        CERR_EXIT("pipe create is error!");

    //结果处理,开启指定多个进程,重新获取进程开启成功数
    cut = bench(cut, argv[2], pfds[1]);    

    //这里读取管道信息
    fx = fdopen(pfds[0], "r");
    if(NULL == fx)
        CERR_EXIT("fdopen pfds[0]:%d error.", pfds[0]);

    //统计最后数据
    setbuf(fx, NULL);
    while(cut > 0){
        int s, f, b;
        len = fscanf(fx, "%d %d %d", &s, &f, &b);    
        if(len < 3){
            CERR("fscnaf read error! len:%d.", len);
            break;
        }
        speed += s;
        failed += f;
        bytes += b;            
        --cut;        
    }
    fclose(fx);
    close(pfds[0]);
    close(pfds[1]);

    //输出统计结果
    puts("***********-----------------------------------------------------------***********");
    printf("Collect %.2f pages/min, %.2f kb/sec. Request %d sucess, %d failed.\n",
        (speed+failed)*60.0f/_INT_END, bytes/1024.0f/_INT_END, speed, failed);
    puts("***********-----------------------------------------------------------***********");

    return 0;
}

创造管道,调用多进度处理函数,汇总最终结果.注意一点是打开的管道最终索要本人关闭.(只怕那边有坑),回头看一下,代码其实

抑或相比基础的,首要用的就是Linux编程相关的学识点.

最后输出 每分钟请求的页面数, 每秒请求的bit流,请求成功多少次,请求战败多少次.

 

4.看案例结果 

首选看上边贰个操作图,先请求百度尝试

美高梅娱乐4858.com 3

说到底计算结果是 每分钟请求了6357个界面左右,开启了2二个子进度, 成功24拾肆个,十八个错误. 总的而言百度的分流着实无误,负载均衡强.

再来请求3个普通网站的截图

美高梅娱乐4858.com 4

地点打印很多connect error,意思是过多进度请求链接失利,短期多量链接造成对方服务器拒绝链接, 负载均衡差,

流量差不离,大概和网速有关,请求界面数挺多的那一个界面不错,恐怕是纯静态的. 对于详细查看为何失利,可以在笔录 failed++的时候打印日志看看,

那边就像是此了. 麻雀虽小,能用就好. 完整测试 demo 如下

webtest.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//控制台打印错误信息, fmt必须是双引号括起来的宏
#ifndef CERR
#define CERR(fmt, ...) \
    fprintf(stderr,"[%s:%s:%d][error %d:%s]" fmt "\r\n",\
         __FILE__, __func__, __LINE__, errno, strerror(errno),##__VA_ARGS__)

//检测并退出的宏
#define CERR_EXIT(fmt, ...) \
    CERR(fmt, ##__VA_ARGS__), exit(EXIT_FAILURE)

#endif/* !CERR */

// url长度限制 和 请求串长度限制
#define _INT_URL (1024)
#define _INT_REQ (2048)
//主机地址的最大长度
#define _INT_PORT (255)
//等待时间,在60s后就不在处理了
#define _INT_END  (23)

//简单结构
struct iport{
    short port;
    char ip[_INT_PORT];
};

//默认全局标识, 控制开关
volatile int v_timer = 0;

//闹钟信号,当它启动那一刻就表示可以退下了.
static void __alarm(int sig)
{
    v_timer = 1;
}

/*
 * 执行的主要方法,结果会通过写管道 wfd写入
 */
void bcore(struct iport* ips, const char* req, int wfd);

/*
 * 只接受完整请求 
 * 例如
 * brequest("http://192.168.1.162:80/", ...) 或 http://www.baidu,com
 * 通过url拼接请求串,并返回访问结构
 */
struct iport* brequst(const char* url, char rqs[], int len);
//请求主方法,客户端,返回开启的子进程数
int bench(int cut, const char* url, int wfd);

/*
 * 请求链接主机,根据ip或url
 *
 * host    : url地址
 * port : 请求的端口号
 */
int contweb(const char* host, int port);

// 主函数业务,从这开始
int main(int argc, char* argv[])
{
    int cut, len; //开启进程数量 和 读取scanf返回值
    int pfds[2];    
    FILE* fx;
    int speed = 0, failed = 0, bytes = 0;

    //简单检测    
    if((argc != 3) || (cut = atoi(argv[1]))<=0 || cut > USHRT_MAX){        
        CERR_EXIT(
             "\r\nuage:   ./webtest.out [cut] [url]"
            "\r\n    :=> ./webtest.out 19 http://www.baidu.com/"
        );
    }    

    //创建管道 进行测试, 代码比较杂,需要一些Linux基础知识,多练习
    if(pipe(pfds)<-1)
        CERR_EXIT("pipe create is error!");

    //结果处理,开启指定多个进程,重新获取进程开启成功数
    cut = bench(cut, argv[2], pfds[1]);    

    //这里读取管道信息
    fx = fdopen(pfds[0], "r");
    if(NULL == fx)
        CERR_EXIT("fdopen pfds[0]:%d error.", pfds[0]);

    //统计最后数据
    setbuf(fx, NULL);
    while(cut > 0){
        int s, f, b;
        len = fscanf(fx, "%d %d %d", &s, &f, &b);    
        if(len < 3){
            CERR("fscnaf read error! len:%d.", len);
            break;
        }
        speed += s;
        failed += f;
        bytes += b;            
        --cut;        
    }
    fclose(fx);
    close(pfds[0]);
    close(pfds[1]);

    //输出统计结果
    puts("***********-----------------------------------------------------------***********");
    printf("Collect %.2f pages/min, %.2f kb/sec. Request %d sucess, %d failed.\n",
        (speed+failed)*60.0f/_INT_END, bytes/1024.0f/_INT_END, speed, failed);
    puts("***********-----------------------------------------------------------***********");

    return 0;
}

/*
 * 请求链接主机,根据ip或url
 *
 * host    : url地址
 * port : 请求的端口号
 */
int 
contweb(const char* host, int port)
{
    int sd;
    in_addr_t ia;
    struct sockaddr_in sa = { AF_INET };    
    struct hostent *hp;

    ia = inet_addr(host);
    if(ia != INADDR_NONE)
        memcpy(&sa.sin_addr, &ia, sizeof(ia));
    else {
        hp = gethostbyname(host);
        if(hp < 0){
            CERR("gethostbyname %s error!", host);
            return -1;
        }
        memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);    
    }
    if((sd=socket(PF_INET, SOCK_STREAM, 0))<0){
        CERR("socket SOCK_STREAM");
        return sd;
    }    

    //连接主机
    sa.sin_port = htons(port);
    if(connect(sd, (struct sockaddr*)&sa, sizeof sa)<0){
        CERR("connect sd:%d error!", sd);
        return -1;
    }

    return sd;    
}

//通过url拼接请求串
struct iport* 
brequst(const char* url, char rqs[], int len)
{
    static struct iport __ips;
    //请求的主机, 中间用的url, 临时数据
    const char *hurl, *tmp;        
    char c;
    int pt = 0;//临时用的int变量

    //简单检查参数检查,检查数组大小,url是否合法
    if(len<_INT_REQ || !url || !*url || strlen(url)>_INT_URL)
        CERR_EXIT("params url:%s, len[>=%d];%d error.", url, _INT_REQ, len);    
    //检测url是否是http请求的url,也比较简单,复杂检查要用正则表达式
    hurl = strstr(url, "://");
    if(!hurl || strncasecmp(url, "http", 4))
        CERR_EXIT("url is err [%s]!", url);
    //简单初始化
    memset(rqs, 0, len);    
    memset(&__ips, 0, sizeof __ips);

    //这种代码可以优化,用指针替代数组索引
    strcat(rqs, "GET ");
    hurl += 3; //跳过 "://"指向下一个字符

    //解析url 上是否有端口信息
    tmp = index(hurl, ':');
    if(tmp && tmp < index(hurl, '/')){ 
        strncpy(__ips.ip, hurl, tmp - hurl);
        //没有做安全检查
        while((c=*++tmp)!='\0' && c!='/'){
            if(c<='9' && c>='0'){
                pt = 10*pt + c - '0';
                continue;
            }
            CERR_EXIT("url is error [%s].", url);        
        }
    }    
    else{
        pt = 80; //默认端口
        //这句话意思 是 将 www.baidu.com/ 其中/之前的地方写入到 ip[]中
        strncpy(__ips.ip, hurl, strcspn(hurl, "/"));    
    }
    __ips.port = pt;    

    //将这些内容链接到rqs中
    strcat(rqs, hurl + strcspn(hurl, "/"));
    //采用HTTP1.1 协议
    strcat(rqs, " HTTP/1.1\r\n");
    //添加请求方
    strcat(rqs, "User-Agent: Happy is good.\r\n");
    //上面这样解析有点慢,最快的是整体for,但是更难维护
    strcat(rqs, "Host: ");
    strcat(rqs, __ips.ip);
    strcat(rqs, "\r\n");
    //拼接串最后,连接状态,完毕就关闭
    strcat(rqs, "Connection: close\r\n");
    //拼接空行, 上面可以优化
    strcat(rqs, "\r\n");

    //最终检测,是否字符串太长了
    if(rqs[len-1])
        CERR_EXIT("get http too len!");

    return &__ips;            
}

/*
 * 执行的主要方法,结果会通过写管道 wfd写入
 */
void 
bcore(struct iport* ips, const char* req, int wfd)
{
    int srv, len, rlen;
    int speed = 0, failed = 0, bytes = 0;
    FILE* fx;
    char buf[_INT_REQ];    

    //先注册信号
    if(SIG_ERR == signal(SIGALRM, __alarm))
        CERR_EXIT("signal SIGALRM error!");
    alarm(_INT_END);

    len = strlen(req);    
    for(;;){
        if(v_timer){ //结束之前减一,认为成功过
            if(failed>0)
                --failed;
            break;
        }        

        srv = contweb(ips->ip, ips->port);
        if(srv < 0){
            ++failed;
            continue;    
        }
        //开始写入数据
        if(len != write(srv, req, len)){
            ++failed;
            close(srv);
            continue;
        }
        //下面读取数据,v_timer标志是否超时,超时直接走
        for(;!v_timer;){
            rlen = read(srv, buf, _INT_REQ);                
            if(rlen < 0){ //不考虑软中断了,有问题直接退出
                ++failed;
                close(srv);
                goto __bcore_exit; //退出结算
            }
            if(rlen == 0)//服务端关闭,结束读取
                break;
            bytes += rlen;
        }
        close(srv);
        ++speed;
    }    

__bcore_exit:
    //管道写入
    fx = fdopen(wfd, "w");
    if(NULL == fx)    
        CERR_EXIT("fdopen wfd:%d error!", wfd);
    fprintf(fx,"%d %d %d\n", speed, failed, bytes);    
    fclose(fx);
}

//请求主方法,客户端,返回开启子进程数
int 
bench(int cut, const char* url, int wfd)
{
    int i, rt = 0;//rt 记录正常开启的进程
    pid_t pid;
    char req[_INT_REQ];
    struct iport* ips;

    //这里初始化一些环境
    ips = brequst(url, req, sizeof req);    
    puts("***********-----------------------------------------------------------***********");
    puts(req); //打印数据
    puts("***********-----------------------------------------------------------***********");

    for(i=0; i<cut; ++i){
        pid = fork(); //狂开进程了
        if(pid <= 0){
            sleep(1);//别让它太快完毕,父进程来不及收尸
            break;//结束子进程继续
        }
        ++rt;
    }        
    if(pid < 0)
        CERR_EXIT("child %d process create error!", i);
    if(pid == 0){ //子进程处理
        bcore(ips, req, wfd);
        exit(EXIT_SUCCESS);//子进程这里就结束了
    }
    //下面是父进程处理
    return rt;                    
}

编译代码如下

gcc -Wall -o webtest.out webtest.c

前面就要求我们尝试了,用的还凑合者.

光鲜的骨子里都以平凡.喜欢才是人那台机械的最好能源.

 

后记

  错误是免不了,欢迎指正互换,共同消磨有趣的时光.
( ^_^ )/~~拜拜

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注