悠闲的测试和生活。。。 www.happy4tao.com

发布新日志

  • LoadRunner编程之文件的操作

    2010-08-23 08:55:32


    这篇文章主要写下LoadRunner下如何进行文件的操作。
    1,文件的声明
        LoadRunner不支持FILE数据类型,所以在LoadRunner中用int来声明一个文件:
         int MyFile;
    2,文件的打开
         fopen():返回一个FILE数据类型的指针.因为LoadRunner不支持FILE数据类型,所以返回值需要转化成int型.
          int MyFile;
          MyFile=(int)fopen("C:\\temp\\loans.txt","w");
          fopen()函数的第一个参数是创建文件的路径.第二个参数指定了创建文件的模式.下面是常用的几种模式:
    “w” - 写,当需要往文件中写的时候.如果文件存在,就覆盖该文件,如果文件不存在,根据第一个参数来创建新文件.
    “r” –读,需要从文件中读的时候.这个文件必须已经存在.
    “a” –附加,当往文件末尾添加数据时用到.
    “rw” –读和写.
    第一个参数中注意文件路径为"\\",因为"\"在C语言中为转义字符.另外,如果文件和脚本在同一个目录中,文件的完整路径可以省略.
    3,读文件
           fscanf():用来读文件。函数语法如下:
          int MyFile;
               int LoanNumber;
               MyFile = fopen(“C:\\temp\\loans.txt”,”r”);
               fscanf(MyFile,”%d”, &LoanNumber);
        需要注意的是:MyFile是个文件指针(在LoadRunner中并不是真正的指针),被用来代替实际的文件。所有文件的操作都是使用文件指针而不是文件名称。
        练习1:
        先创建一个文件c:\temp\loans.txt,文件包含的内容为:
        11111
        22222
        33333
        44444
        55555
    循环读取并显示该文件中的每行数据,脚本如下:
    Action()
    {
           int MyFile;
           int LoanNumber,i;
           // Assigning the file path to a string
           char FileName[80] = "C:\\temp\\loans.txt";
     
     
           // Opening the file
           // Note the use of variable to replace the file path
           //
           MyFile = (int)fopen(FileName,"r");
     
     
           // Reading and printing one loan number at a time
           for(i=1;i<=5;i++)
                  {
                  fscanf(MyFile,"%d", &LoanNumber);
                  lr_output_message("Loan Number %d: %d",i,LoanNumber);
                  }
     
           fclose(MyFile);
     
           return 0;
    }
    当文件打开之后,文件指针在文件的最开始。每读一次,指针就移动到下一行,这就是为什么程序能自动读取下面元素的原因。
    a) 如果把循环改为for(i=1;i<=7;i++),会出现什么样的结果呢?
    会出现三个都是打印55555的结果,原因是文件指针移动到最后就不再移动了,但是有7次循环,那多出来的2次循环打印的数据仍然是最后一行的数据。
    b)如果不知道该文件下包含数据的行数,就无法用for循环。需要使用while循环。可以使用feof函数。feof(MyFile)在文件指针没有到达返回文件末尾的时候返回0,如果到末尾返回非0值。这样可以修改程序的循环为:
          while(feof(MyFile)== 0);
    注意:如果文件末尾有空行,feof也会把它最为文件的一部分。
    4,写文件
      fprintf():用来往文件写。语法如下:
              int MyFile;
            char Name[] = “John Doe”;
            MyFile = fopen(“C:\\temp\\loan.txt”,”w”);
                  fscanf(MyFile,”%s”,Name);
    第一个参数是文件指针,第二个参数是格式,第三个参数是指定格式对应的变量。
    Action()
    {
           int MyFile;
           char Name[] = "John Doe";
     
     
           MyFile = fopen("C:\\temp\\names.txt","w");
    // note that "w" is used to write
          
    fprintf(MyFile,"%s", Name);
    // note that we are printing a string here
    转载请注明源自www.SCMLife.com,请保留版权. 本贴地址:http://bbs.scmlife.com/viewthread.php?tid=23466
     
  • 把sitescope的破解码给大家共享一下!

    2009-12-08 16:26:00

    把sitescope的破解码给大家共享一下!


    我试过了HP SiteScope LR 9.0 也是没问题的...


    // Permanent Edition
    // Generated 2005 By NiTROUS
    // Expires: Never
    // Users #: 99998
    // ENJOY!
    //
    // NOTE: Paste the Option License as One Line, if you get Invalid
    // License Notice, check you copied the entire buffer!
    //
    // - NiTROUS

    Main License:
    PM90815892099998-99101472

    Option Licenses:
    PM90815892099998-017203,PM90815892099998-027574,PM90815892099998-037997,PM90815892099998-041528,PM90815892099998-051001,PM90815892099998-061194,PM90815892099998-078175,
    PM90815892099998-084124,PM90815892099998-095141,PM90815892099998-108303,PM90815892099998-119872,PM90815892099998-129167,PM90815892099998-132034,PM90815892099998-140499,
    PM90815892099998-153772,PM90815892099998-162453,PM90815892099998-174058,PM90815892099998-181689,PM90815892099998-190440,PM90815892099998-207770,PM90815892099998-212611,
    PM90815892099998-220812,PM90815892099998-235193,PM90815892099998-244222,PM90815892099998-255791,PM90815892099998-262000,PM90815892099998-276021,PM90815892099998-283762,
    PM90815892099998-295733,PM90815892099998-308129,PM90815892099998-310246,PM90815892099998-322509,PM90815892099998-331480,PM90815892099998-349403,PM90815892099998-353542,
    PM90815892099998-369063,PM90815892099998-376796,PM90815892099998-380343,PM90815892099998-390738,PM90815892099998-405616,PM90815892099998-413033,PM90815892099998-425874,
    PM90815892099998-432511,PM90815892099998-462026,PM90815892099998-478267,PM90815892099998-481432,PM90815892099998-494545,PM90815892099998-509005,PM90815892099998-510644,
    PM90815892099998-529291,PM90815892099998-536670,PM90815892099998-545993,PM90815892099998-554048,PM90815892099998-562505,PM90815892099998-579566,PM90815892099998-582971,
    PM90815892099998-598500,PM90815892099998-600422,PM90815892099998-612447,PM90815892099998-622760,PM90815892099998-636043,PM90815892099998-644214,PM90815892099998-655221,
    PM90815892099998-668884,PM90815892099998-674913,PM90815892099998-682866,PM90815892099998-692743,PM90815892099998-708517,PM90815892099998-710690,PM90815892099998-727897,
    PM90815892099998-734012,PM90815892099998-740729,PM90815892099998-756326,PM90815892099998-762779,PM90815892099998-770088,PM90815892099998-783363,PM90815892099998-794342,
    PM90815892099998-807812,PM90815892099998-817531
  • 在redhat上安装net-snmp

    2009-12-08 09:57:49

    在redhat上安装net-snmp

    默认分类   2009-09-29 17:57   阅读111   评论0  
    字号:    
    在redhat上安装net-snmpnet-snmp 的安装和配置
    从以下地址可以下载到最新的软件安装包:
    http://nchc.dl.sourceforge.net/sourceforge/net-snmp/net-snmp-5.4.2.1.tar.gz
    1、解压源码包:
    tar –zxvf net-snmp-5.4.2.1.tar.gz
    2、进入解压后的文件目录:
    cd net-snmp-5.4.2.1
    3、执行文件目录下的configure可执行文件,如果想指定程序包的安装路径,那么您首先建立相应的文件夹来存放安装信息,您可以写成./configure –prefix=/您指定的路径名。参数—prefix用来告诉系统安装信息存放的路径,如果您没有指定路径,直接执行./configure,那么程序包都会安装在系统默认的目录下,通常为:/usr/local下。例如:
    ./configure --prefix=/usr/local/snmp //配置 指定安装目录,安装过程会询问您以下的信息:
    注意:以下问题似乎不怎么重要,那好像仅仅是官方想了解使用本软件方的信息,可以直接回车而不用回答,系统会采用默认信息,其中日志文件默认安装在/var/log/snmpd.log.数据存贮目录默认存放在/var/net-snmp下。
    default version of-snmp-version(3): 3(在这里版本通常有三种形式:1,2c,3)
    Systemcontact information(配置该设备的联系信息): heaven(也可以是邮箱地址)
    System location (该系统设备的地理位置):BEIJING P.R China
    Location to write logfile (日志文件位置): /var/log/snmpd.log
    Location to Write persistent(数据存储目录): /var/net-snmp
    4、#make
    编译源码包文件,通常只需要执行make命令,系统会根据Makefile层层进行编译,第一次编译这需要大约20分钟的时间哦,您需要有耐心等待(RedHat4系统通常会相继出现两个编译错误,您此时可以参考我在本页后面写的出错处理方式来解决). 如果make 成功的话,那么紧接着安装程序了,这一步一般不会出现怪异的错误,安装也比较费时,大约要花费10分钟呢.

    #make install
    5、在完成上面的步骤后紧接着制作配置文件  *.conf,在这里有两种方式,一种方式是用命令snmpconf -g basic_setup生成snmpd.conf文件,但需要回答很多没用的问题,比较费时,我这里用了一种较简便的方法生成配置文件,就是把解压后的那个文件目录下的EXAMPLE.conf文件拷在我们的安装路径下并修改,命令格式如下:
    cp EXAMPLE.conf /usr/local/snmp/snmpd.conf //cp样例配置到安装目录下
    6、vi /usr/local/snmp/snmpd.conf //编辑配置文件
    把里面的NETWORK 改成需要查看snmp信息的主机ip 地址
    把COMMUNITY改成你设定的值(自己起个字符串形式的名字)。
    然后保存退出
    7、/usr/local/sbin/snmpd –c /usr/local/snmp/snmpd.conf & //启动snmp
    8、netstat -an  //查看snmp是否启动
    9、在脚本里配置snmp,使其在开机时自启动snmpd服务。(也可以不写在脚本里,每次系统启动后执行一下第7步就行了)。在脚本里的编写:
    vi /etc/rc.local
    添加 usr/local/sbin/snmpd –c /usr/local/snmp/snmpd.conf &
    10、关闭snmp服务
    ps aux |grep snmp |grep -v grep |awk '{print $2}' |xargs kill
    11出错处理机制
    也许在执行第四不步make后,过了一会儿程序退出,并提示一下错误:
    Grep /usr/lib/libbeecrypt.la: No such file or directory
    /bin/sed: can't read /usr/lib/libbeecrypt.la: No such file or directory
    libtool: link: `/usr/lib/libbeecrypt.la' is not a valid libtool archive
    make[1]: *** [libnetsnmpmibs.la] Error 1
    make[1]:Leavingdirectory /email/share/ceno_soft/net-snmp-5.4.1/agent'
    make: *** [subdirs] Error 1
    解决方法
    说明缺少libbeecrypt.la ,libbeecrypt.so等共享库
    如果确认系统中有libbeecrypt.la,也许他安装在/usr/local下面,可尝试:
    ln -s /usr/local/lib/libbeecrypt.la /usr/lib/libbeecrypt.la
    如果/usr/local下面没有,那么你必须安装beecrypt
    下载路径
    http://nchc.dl.sourceforge.net/sourceforge/beecrypt/beecrypt-4.1.2.tar.gz
    解压并安装到/usr目录下:
    tar -zxvf beecrypt-4.1.2.tar.gz
    ./configure -prefix=/usr
    #默认是安装在/usr/local,我们需要安装在/usr目录下。如果没有加这个参数需要做连接
    ln -s /usr/local/lib/libbeecrypt.la /usr/lib/libbeecrypt.la
    编译并安装beecrypt库,先执行make编译源码包文件编译成功后执行安装命令make install,其命令如下:
    #make
    #make install
    好,beecrypt安装完成后,我们继续NET-SNMP的编译,执行一下make 命令。
    当我们继续make的时候,第一个错消逝了,但不幸的是出现了一个新的错误,错误提示如下:rpath -Wl,/usr/local/lib
    /usr/bin/ld: cannot find –lelf
    collect2: ld returned 1 exit status
    make[1]: *** [snmpd] Error 1 make[1]: Leaving directory `/local/akazam/cacti/bak/net-snmp-5.4.2/agent'
    make: *** [subdirs] Error 1
    ke[1]: Leaving directory `/local/akazam/cacti/bak/net-snmp-5.4.2/agent
    make: *** [subdirs] Error 1
    解决方法
    执行命令: ln -s /usr/lib/libelf.so.1  /usr/lib/libelf.so
    现在估计该装的软件包都已经装上了,链接库也差不多了吧,我们现在可以大胆的回到net-snmp-5.4.2.1目录下,继续从第4步往下执行,这样就一路畅通了。
  • Loadrunner监控linux( 转)

    2009-12-02 12:03:04

    Loadrunner监控linux(

    lr中配置
    从LR里面add measurement,填写linux机器的IP,出现所有unix/linux的计数器,包括cpu的,mem的,disk,network的。介绍几个常用的:
    average load :在过去的1分钟,的平均负载
    cpu utilization: cpu的使用率
    disk traffic: disk传输率
    paging rate 每秒从磁盘读到物理内存,或者从物理内存写到页面文件的内存页数
    Swap-in rate: 每秒交换到内存的进程数
    Swap-out rate: 每秒从内存交换出来的进程

    下列默认度量可用于 UNIX 计算机:

    度量

    描述

    Average load

    上一分钟同时处于“就绪”状态的平均进程数

    Collision rate

    每秒钟在以太网上检测到的冲突数

    Context switches rate

    每秒钟在进程或线程之间的切换次数

    CPU utilization

    CPU 的使用时间百分比

    Disk rate

    磁盘传输速率

    Incoming packets error rate

    接收以太网数据包时每秒钟接收到的错误数

    Incoming packets rate

    每秒钟传入的以太网数据包数

    Interrupt rate

    每秒内的设备中断数

    Outgoing packets errors rate

    发送以太网数据包时每秒钟发送的错误数

    Outgoing packets rate

    每秒钟传出的以太网数据包数

    Page-in rate

    每秒钟读入到物理内存中的页数

    Page-out rate

    每秒钟写入页面文件和从物理内存中删除的页数

    Paging rate

    每秒钟读入物理内存或写入页面文件的页数

    Swap-in rate

    正在交换的进程数

    Swap-out rate

    正在交换的进程数

    System mode CPU utilization

    在系统模式下使用 CPU 的时间百分比

    User mode CPU utilization

    在用户模式下使用 CPU 的时间百分比


    补充一些常见的问题及处理方法:
    1在执行配置或安装命令过程中出现“拒绝的权限”的提示;
    答:是由于文件的权限引起的,应该给当前用户所有文件的“777”权限,即完全控制权限。

    2安装好后从LoadRunner中看不到信息,但是没有报错;
    答:可能是返回的信息值比较小,所以在图中几乎看不到,例如:如果没有运行程序的话,CPU的使用率接近于0,所以在监视图中看不到变化。也有可能是采样的频率过大,可以在图表中设置没1秒获取一次信息,这样界面就刷新的比较及时了。

    3监视一段时间后LoadRunner中提示有错误发生不能继续监视到信息;
    答:可能是由于CPU长时间处于高负荷状态,而导致系统自动关闭了该服务。可以在LoadRunner中重新加一次计数器,并且设置取样的时间稍长一点,就会避免这种情况。

    4以前用LoadRunner监视都是成功的,但是再次监视不到信息;
    答:有可能是由于系统重新启动,而没有打开rstatd守护进程。可以手工重新打开一次,使用命令“rpc.rstatd”,另外可以使用“rpcinfo -p”命令来查看当前系统是否已经启动了rstatd守护进程

  • linux教程:通过LoadRunner监控Linux的资源状况 (转)

    2009-12-02 11:51:46

    linux教程:通过LoadRunner监控Linux的资源状况

    我们在使用LR进行性能测试的时候,经常有需要监控OS的资源使用情况的需求。

    对于 Windows系统,这个工作进行起来很方便,直接在LR的资源监控窗口中添加需要被监控的机器名或IP即可,但对于Linux/Unix系统,则要稍微复杂一些,我在这里简单介绍一下如何在LR中监控Linux/Unix系统的资源使用情况:

    Linux

    对于Linux系统,要想通过LR监控Linux/Unix系统的资源使用情况,需要运行rstatd服务。如果OS没有安装rstatd(可以查找一下系统中是否存在rpc.rstatd这个文件,如果没有,则说明系统没有安装 rstatd),则需要进行安装。

    rstatd安装步骤如下:

    获得rstatd的安装介质(rstatd.tar.gz)。rstatd可以从 redhat的安装CD中获得,或者从网站上下载(给出一个下载地址,sourceforge的: //heanet.dl.sourceforge.net/sourceforge/rstatd)。

    将rstatd.tar.gz拷贝到Linux系统中,解压,赋予可执行权限,进入rpc.rstatd目录,依次执行如下命令:

    #./configure
    #make
    #make install


    结束后,运行./rpc.rstatd命令,启动服务。这个时候,你就可以在LR中监控Linux资源了。

    Unix

    对于Unix系统,比如Solaris,AIX或者HP UX等,它们的配置过程比较简单——在inetd.conf(在/etc目录下)文件中去掉rstatd前面的注释,然后启动rstatd服务即可

  • LoadRunner下载文件的实验(转)

    2009-11-26 09:58:36

    LoadRunner下载文件的实验

    字体:        | 上一篇 下一篇 | 打印  | 我要投稿  | 每周一问,答贴有奖

            今天用LoadRunner进行下载web网站上文件的试验,首先学习了关河Blog中的文章(用LoadRunner下载文件并保存到本地 )写了个脚本,运行后却发现该脚本对于二进制文件类型(如rar、bmp等)下载正常,但对于文本文件类型(如txt、xml)等确有问题,问题在于对文件大小的判断问题。

            在关河的脚本中,通过flen = web_get_int_property(HTTP_INFO_DOWNLOAD_SIZE);来获取要下载文件的大小。
            对于二进制文件,运行日志
    web_link("aa.bmp ") highest severity level was "warning", 824 body bytes, 197 header bytes
    flen:1021
            文件大小1021字节,包括197字节的header和824字节的body

            对于文本文件,运行日志:
    web_link("test.xml") was successful, 277 body bytes, 203 header bytes
    flen:480
            下载生成的文件大小480字节,包括了227字节的body和字节203的header,打开该xml文件内容有错。其实真正的文件大小是227字节,就是body部分。

            修改了脚本,把上面获取文件大小的语句改为flen = strlen(lr_eval_string("{fcontent}")); ,
            只取body部分作为文件内容,结果就可以了。
            运行日志:
    web_link("test.xml") was successful, 277 body bytes, 203 header bytes
    flen:277

            但是,用该方式却又无法正确下载二进制文件,估计对于二进制文件不能用该方式来获取文件大小,目前没有两全其美的方法,希望有朋友可以指点迷津。

            脚本如下:

    Action()
    {
        
    int flen;
        
    long filedes;
        
    char filename[1024];    

        web_add_cookie(
    "seraph.os.cookie=ElKlHkQmJlOkFjGjJi; DOMAIN=172.20.16.4");

        web_set_max_html_param_len(
    "1024000");    
        web_url(
    "172.20.16.4:8080"
            
    "URL=http://172.20.16.4:8080/"
            
    "Resource=0"
            
    "RecContentType=text/html"
            
    "Referer="
            
    "Snapshot=t4.inf"
            
    "Mode=HTML"
            EXTRARES, 
            
    "Url=/styles/global.css""Referer=http://172.20.16.4:8080/secure/Dashboard.jspa", ENDITEM, 
            LAST);

        web_link(
    "TEST-306"
            
    "Text=TEST-306"
            
    "Snapshot=t5.inf"
            EXTRARES, 
            
    "Url=../styles/global.css", ENDITEM, 
            LAST);    
        
      web_reg_save_param(
    "fcontent""LB=""RB=""SEARCH=BODY", LAST);
        web_link(
    "test.xml"
            
    "Text=test.xml"
            
    "Snapshot=t6.inf"
            LAST);
        
        
    //获取文本类型的文件大小
        flen = strlen(lr_eval_string("{fcontent}"));
        
    //获取二进制文件类型的文件大小
        
    //flen = web_get_int_property(HTTP_INFO_DOWNLOAD_SIZE);    
        lr_message("-----------------flen:%d",flen);
        
        
    //生成随机的文件名称,便于并发
        strcpy(filename,"d:\\123\\aa_");
      strcat(filename,lr_eval_string(
    "{Num}"));
        strcat(filename,
    ".xml");
        
        
    if(flen > 0)    
        
    {
            
    //以写方式打开文件
            if((filedes = fopen(filename, "wb")) == NULL)
            
    {
                lr_output_message(
    "Open File Failed!");
                
    return -1;
            }

            
    //写入文件内容
            fwrite(lr_eval_string("{fcontent}"), flen, 1, filedes);
            
    //关闭文件
            fclose(filedes);
        }


        
    return 0;
    }
            以下为关河大哥的解答,对此深表感谢: 

            根据我的理解,其实这个问题的原因其实不复杂,但解决方法似乎只能是针对不同类型的文件自行处理。 

            web_get_int_property函数获得的是上一次web函数获得响应的总的大小(包括head和body部分),由于对二进制文件,返回的数据包是没有head部分的,因此得到的大小就是二进制文件的大小,可以用web_get_int_property函数得到的值作为该文件的实际大小,至于不能用strlen方式获得下载二进制文件的大小,原因是二进制文件的内容中肯定会出现'\0'这样的字符,导致strlen函数判断失败。 

            而对于Txt和XML等文件,返回的数据包中是包含head部分的,因此不能用web_get_int_property函数获得的download size来作为文件本身的大小。 

            我能想到的可行的解决方案是:针对不同的文件采用不同的方法,如果需要在脚本中判断文件类型的话,可以针对下载文件的文件名后缀决定采用何种方式。
  • Web service到底是什么;在什么情况下你应该使用Web service。

    2009-09-29 12:03:07

     

    Web service到底是什么;在什么情况下你应该使用Web service。

    分布式应用程序和浏览器

    研究一下当前的应用程序开发,你会发现一个绝对的倾向:人们开始偏爱基于浏览器的瘦客户应用程序。这当然不是因为瘦客户能够提供更好的用户界面,而是因为它能够避免花在桌面应用程序发布上的高成本。发布桌面应用程序成本很高,一半是因为应用程序安装和配置的问题,另一半是因为客户和服务器之间通信的问题。

    传统的Windows富客户应用程序使用DCOM来与服务器进行通信和调用远程对象。配置好DCOM使其在一个大型的网络中正常工作将是一个极富挑战性的工作,同时也是许多IT工程师的噩梦。事实上,许多IT工程师宁愿忍受浏览器所带来的功能限制,也不愿在局域网上去运行一个DCOM。在我看来,结果就是一个发布容易,但开发难度大而且用户界面极其受限的应用程序。极端的说,就是你花了更多的资金和时间,却开发出从用户看来功能更弱的应用程序。不信?问问你的会计师对新的基于浏览器的会计软件有什么想法:绝大多数商用程序用户希望使用更加友好的Windows用户界面。

    关于客户端与服务器的通信问题,一个完美的解决方法是使用HTTP协议来通信。这是因为任何运行Web浏览器的机器都在使用HTTP协议。同时,当前许多防火墙也配置为只允许HTTP连接。

    许多商用程序还面临另一个问题,那就是与其他程序的互操作性。如果所有的应用程序都是使用COM或.NET语言写的,并且都运行在Windows平台上,那就天下太平了。然而,事实上大多数商业数据仍然在大型主机上以非关系文件(VSAM)的形式存放,并由COBOL语言编写的大型机程序访问。而且,目前还有很多商用程序继续在使用C++、Java、Visual Basic和其他各种各样的语言编写。现在,除了最简单的程序之外,所有的应用程序都需要与运行在其他异构平台上的应用程序集成并进行数据交换。这样的任务通常都是由特殊的方法,如文件传输和分析,消息队列,还有仅适用于某些情况的的API,如IBM的"高级程序到程序交流(APPC)"等来完成的。在以前,没有一个应用程序通信标准,是独立于平台、组建模型和编程语言的。只有通过Web Service,客户端和服务器才能够自由的用HTTP进行通信,不论两个程序的平台和编程语言是什么。

    什么是Web Service

    对这个问题,我们至少有两种答案。从表面上看,Web service 就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。这就是说,你能够用编程的方法通过Web来调用这个应用程序。我们把调用这个Web service 的应用程序叫做客户。例如,你想创建一个Web service ,它的作用是返回当前的天气情况。那么你可已建立一个ASP页面,它接受邮政编码作为查询字符串,然后返回一个由逗号隔开的字符串,包含了当前的气温和天气。要调用这个ASP页面,客户端需要发送下面的这个HTTP GET请求:

    http://host.company.com/weather.asp?zipcode=20171

    返回的数据就应该是这样:

    21,晴

    这个ASP页面就应该可以算作是Web service 了。因为它基于HTTP GET请求,暴露出了一个可以通过Web调用的API。当然,Web service 还有更多的东西。

    下面是对Web service 更精确的解释: Web services是建立可互操作的分布式应用程序的新平台。作为一个Windows程序员,你可能已经用COM或DCOM建立过基于组件的分布式应用程序。COM是一个非常好的组件技术,但是我们也很容易举出COM并不能满足要求的情况。

    Web service平台是一套标准,它定义了应用程序如何在Web上实现互操作性。你可以用任何你喜欢的语言,在任何你喜欢的平台上写Web service ,只要我们可以通过Web service标准对这些服务进行查询和访问。

    新平台

    Web service平台需要一套协议来实现分布式应用程序的创建。任何平台都有它的数据表示方法和类型系统。要实现互操作性,Web service平台必须提供一套标准的类型系统,用于沟通不同平台、编程语言和组件模型中的不同类型系统。在传统的分布式系统中,基于界面(interface)的平台提供了一些方法来描述界面、方法和参数(译注:如COM和COBAR中的IDL语言)。同样的,Web service平台也必须提供一种标准来描述Web service,让客户可以得到足够的信息来调用这个Web service。最后,我们还必须有一种方法来对这个Web service进行远程调用。这种方法实际是一种远程过程调用协议(RPC)。为了达到互操作性,这种RPC协议还必须与平台和编程语言无关。下面几个小节就简要介绍了组成Web service平台的这三个技术。

    XML和XSD

    可扩展的标记语言(XML)是Web service平台中表示数据的基本格式。除了易于建立和易于分析外,XML主要的优点在于它既是平台无关的,又是厂商无关的。无关性是比技术优越性更重要的:软件厂商是不会选择一个由竞争对手所发明的技术的。

    XML解决了数据表示的问题,但它没有定义一套标准的数据类型,更没有说怎么去扩展这套数据类型。例如,整形数到底代表什么?16位,32位,还是64位?这些细节对实现互操作性都是很重要的。W3C制定的XML Schema(XSD)就是专门解决这个问题的一套标准。它定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型。Web service平台就是用XSD来作为其数据类型系统的。当你用某种语言(如VB.NET或C#)来构造一个Web service时,为了符合Web service标准,所有你使用的数据类型都必须被转换为XSD类型。你用的工具可能已经自动帮你完成了这个转换,但你很可能会根据你的需要修改一下转换过程。在第二章中,我们将深入XSD,学习怎样转换自定义的数据类型(例如类)到XSD的类型。

    SOAP

    Web service建好以后,你或者其他人就会去调用它。简单对象访问协议(SOAP)提供了标准的RPC方法来调用Web service。实际上,SOAP在这里有点用词不当:它意味着下面的Web service是以对象的方式表示的,但事实并不一定如此:你完全可以把你的Web service写成一系列的C函数,并仍然使用SOAP进行调用。SOAP规范定义了SOAP消息的格式,以及怎样通过HTTP协议来使用SOAP。SOAP也是基于XML和XSD的,XML是SOAP的数据编码方式。第三章我们会讨论SOAP,并结识SOAP消息的各种元素。

    WSDL

    你会怎样向别人介绍你的Web service有什么功能,以及每个函数调用时的参数呢?你可能会自己写一套文档,你甚至可能会口头上告诉需要使用你的Web service的人。这些非正式的方法至少都有一个严重的问题:当程序员坐到电脑前,想要使用你的Web service的时候,他们的工具(如Visual Studio)无法给他们提供任何帮助,因为这些工具根本就不了解你的Web

    service。解决方法是:用机器能阅读的方式提供一个正式的描述文档。Web service描述语言(WSDL)就是这样一个基于XML的语言,用于描述Web service及其函数、参数和返回值。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的Web service生成WSDL文档,又能导入WSDL文档,生成调用相应Web service的代码。

  • Jmeter变量参数化及函数应用(转)

    2009-09-09 14:53:22

    我们在使用Jmeter录制脚本后,经常会对已录制的脚本进行修改,需要把一些参数使用一些变量替代,Jmeter是支持这些功能的,不过是通过函数实现的。下面举一个简单的例子,使用随机数替代一个参数:
            打开录制好的脚本,点击Jmeter的“选项”,选择“函数助手对话框”(或者使用快捷键“Ctrl+F”),在“选择一个功能”的下拉框中选择“_Random”,然后在“函数参赛”中会出现三个参数有用户来设置,第一个参数是“一个范围内的最小值”,即所要取的随机数的最小值,我们设置成1;第二个参数是“一个范围内的最大值”,即所要取的随机数的最大值,我们设置成100;第三个参数是“函数名称”,即用于存储在测试计划中其他的方式使用的值,我们设置成Random。设置好上面的三个参数后,点击“生成”按钮,这样就会在对话框的最下面生成一个字符串“${__Random(1,100,Random)}”,然后我们找到要替换的参数,把它的值换成前面生成的字符串就可以了,然后每次运行的时候,这个参数会变成一个1到100之间的随机数。
            我们在上个例子中可以看到Jmeter提供了很多函数,能满足咱们在测试中的大多数需要,下面来讨论几个常用的函数。
            _StringFromFile,这个函数是从一个文件中取到一个字符串,这个函数和LoadRunner中的File变量差不多,不过LoadRunner可以直接从数据库中查询记录,自动生成文件,而Jmeter需要我们借助第三方工具生成文本文件(我们可以通过数据库查询工具查出结果,然后拷贝到一个文本文件中,这样就是40万人民币的软件和免费软件之间的差别,嘿嘿)。生成文本文件后就可以设置这个函数的参数了,参数分别是“输入文件的全路径”,“函数名称”,“Start file sequence number”,Final file sequence number”。第一个参数就是咱们前面生成的文件的完整路径,即文件路径+文件名.扩展名(文件路径可以写成相对路径或绝对路径)。第二个参数是用于存储在测试计划中其他的方式使用的值(其实我也一直不明白这个参数的用处,不设置有些函数也能正常使用,不过最好还是随便设置一下吧,因为还有一些函数不能缺省)。第三和第四个参数的用途有两个,如果一起使用可以从多个文件中读取字符串。如果只使用第四个参数则表示对同一个文件读取多次。

    例如:${_StringFromFile(test#'.'txt,,1,2)} 可以读取test1.txt和test2.txt,多线程使用时,从test1的第一条记录开始读取,test1的记录读取完成后,自动从test2.txt的第一行继续读取。

    ${_StringFromFile(test1.txt,,,2)} 读取test.txt两次,多线程使用时,从test1的第一条记录开始读取,test1的记录读取完成后,再次返回test1.txt的第一行继续读取。以上两种情况时,如果文件中数据读取完成,则循环会自动终止。

             _counter,这个函数是一个计数器,用于统计函数的使用次数,它从1开始,每调用这个函数一次它就会自动加1,它有两个参数,第一个参数是布尔型的,只能设置成“TRUE”或者“FALSE”,如果是TRUE,那么每个用户有自己的计数器,可以用于统计每个线程歌执行了多少次。如果是FALSE,那就使用全局计数器,可以统计出这次测试共运行了多少次。第二个参数是“函数名称”。
            _javaScript,我个人认为这个函数是最好用的函数,通过它能使用JavaScript所支持的所有函数,比如当前的系统日期,系统时间等,它的参数也有两个,第一个是“JavaScript. expression to evaluate”,这个参数是JavaScript的语句表达式,我们可以输入任何的JavaScript支持语句,调用JavaScript自带的函数(可惜不能使用自己写的JavaScript函数,有点遗憾)。第二个参数是“函数名称”。
            _threadNum,这个函数没有任何参数,它用于得到当前运行的线程编号。
            _machineName,这个函数用于返回当前的主机名,有一个参数,是“函数名称”。
            _log,用于记录日志,它可以将一条信息记录到指定的日志文件中,并返回所记录的信息。它有三个参数。第一个是“String to be logged”,即要记录到日志文件中的内容。第二个是“Log level”,即日志的等级,这个参数只能设置成OUT, ERR, DEBUG, INFO,WARN or ERROR,如果这个参数不设置,函数默认为“INFO”。第三个参数是“Throwable text”,即要抛出的文本信息,如果不设置,函数会抛出Java自定义的异常。
            _logn,这个函数和_log的功能一样,参数和使用都完全相同,唯一个差别在于_log会返回记录到日志中的信息,而_logn不返回任何信息。
            _intSum,用于计算多个整数的和,可以是计算正整数和负整数的和,它有N个参数,最少有3个参数,最多不限。最后一个参数是函数名称,前面的其它参数是要求和的整数。这个函数在函数对话框中只显示3个参数,如果要计算多个整数,可以通过添加参数实现,不过最后一个参数一定是函数名称。
            除了上面介绍的几个函数外,Jmeter还支持了更多更强大的函数,比如_BeanShell,_regexFunction等,如果有需要设置更复杂场景的朋友可以仔细研究一下,可以在函数助手对话框中点击“帮助”,读取这些函数的使用帮助(我的英语水平有限,不能准确的翻译函数帮助,就不在这里献丑了)。另外,Jmeter还支持自定义的脚本语言的开发,比如Java和BeanShell等,可以自己写测试语句,咱们下次讨论如何使用Jmeter自定义的语言开发测试脚本,下次再说,嘿嘿。


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/li_ok/archive/2006/12/14/1442495.aspx
  • 什么是压力测试。

    2009-08-17 15:33:48

    压力测试是测试系统在一饱和状态下,例如cpu,内存等在饱和和使用情况下,系统能够处理的会话能力,以及系统是否会出现错误。

    特点: 通过增加访问压力(例如,增加并发的用户数量等),使应用系统的资源使用保持在一定的水平,主要目的是检验此时的应用表现,重点在于有无出错信息产生,系统对应用的响应时间等。

    一般情况下,会把压力设定为: cpu使用率达到75%以上,内存使用率达到70%以上,在这种情况下,测试系统的响应时间,系统有无产生错误。

    这种性能测试方法一搬用于测试系统的稳定性。
       
  • C语言中关于时间的函数

    2009-04-10 22:39:31

    本文从介绍基础概念入手,探讨了在C/C++中对日期和时间操作所用到的数据结构和函数,并对计时、时间的获取、时间的计算和显示格式等方面进行了阐述。本文还通过大量的实例向你展示了time.h头文件中声明的各种函数和数据结构的详细使用方法。 
    关键字:UTC(世界标准时间),Calendar Time(日历时间),epoch(时间点),clock tick(时钟计时单元) 
    1.概念 
    在 C/C++中,对字符串的操作有很多值得注意的问题,同样,C/C++对时间的操作也有许多值得大家注意的地方。最近,在技术群中有很多网友也多次问到过 C++语言中对时间的操作、获取和显示等等的问题。下面,在这篇文章中,笔者将主要介绍在C/C++中时间和日期的使用方法. 
    通过学习许多C/C++库,你可以有很多操作、使用时间的方法。但在这之前你需要了解一些“时间”和“日期”的概念,主要有以下几个: 
    Coordinated Universal Time(UTC): 协调世界时,又称为世界标准时间,也就是大家所熟知的格林威治标准时间(Greenwich Mean Time,GMT)。比如,中国内地的时间与 UTC的时差为+8,也就是UTC+8。美国是UTC-5。 
    Calendar Time:日历时间,是用“从一个标准时间点到此时的时间经 过的秒数”来表示的时间。这个标准时间点对不同的编译器来说会有所不同,但对一个编译系统来说,这个标准时间点是不变的,该编译系统中的时间对应的日历时 间都通过该标准时间点来衡量,所以可以说日历时间是“相对时间”,但是无论你在哪一个时区,在同一时刻对同一个标准时间点来说,日历时间都是一样的。 
    epoch:时间点。时间点在标准C/C++中是一个整数,它用此时的时间和标准时间点相差的秒数(即日历时间)来表示。 
    clock tick:时钟计时单元(而不把它叫做时钟滴答次数),一个时钟计时单元的时间长短是由CPU控制的。一个clock tick不是CPU的一个时钟周期,而是C/C++的一个基本计时单位。 
    我们可以使用ANSI标准库中的time.h头文件。这个头文件中定义的时间和日期所使用的方法,无论是在结构定义,还是命名,都具有明显的C语言风格。下面,我将说明在C/C++中怎样使用日期的时间功能。 
    2. 计时 
    C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t。在MSDN中,查得对clock函数定义如下: 
    clock_t clock( void ); 
    这 个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时 间(wal-clock)。其中clock_t是用来保存时间的数据类型,在time.h文件中,我们可以找到对它的定义: 
    #ifndef _CLOCK_T_DEFINED 
    typedef long clock_t; 
    #define _CLOCK_T_DEFINED 
    #endif 
    很明显,clock_t是一个长整形数。在time.h文件中,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下: 
    #define CLOCKS_PER_SEC ((clock_t)1000) 
    可以看到每过千分之一秒(1毫秒),调用clock()函数返回的值就加1。下面举个例子,你可以使用公式clock()/CLOCKS_PER_SEC来计算一个进程自身的运行时间: 
    void elapsed_time() 

    printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC); 

    当然,你也可以用clock函数来计算你的机器运行一个循环或者处理其它事件到底花了多少时间: 
    /* 测量一个事件持续的时间*/ 
    /* Date : 10/24/2007 */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main( void ) 

        long i = 10000000L; 
        clock_t start, finish; 
        double duration; 
        /* 测量一个事件持续的时间*/ 
        printf( "Time to do %ld empty loops is ", i ); 
        start = clock(); 
        while( i-- ) ; 
        finish = clock(); 
        duration = (double)(finish - start) / CLOCKS_PER_SEC; 
        printf( "%f seconds\n", duration ); 
        system("pause"); 


    在笔者的机器上,运行结果如下: 
    Time to do 10000000 empty loops is 0.03000 seconds 
    上面我们看到时钟计时单元的长度为1毫秒,那么计时的精度也为1毫秒,那么我们可不可以通过改变CLOCKS_PER_SEC的定义,通过把它定义的大一些,从而使计时精度更高呢?通过尝试,你会发现这样是不行的。在标准C/C++中,最小的计时单位是一毫秒。 
    3.与日期和时间相关的数据结构 
    在标准C/C++中,我们可通过tm结构来获得日期和时间,tm结构在time.h中的定义如下: 
    #ifndef _TM_DEFINED 
    struct tm { 
    int tm_sec; /* 秒 – 取值区间为[0,59] */ 
    int tm_min; /* 分 - 取值区间为[0,59] */ 
    int tm_hour; /* 时 - 取值区间为[0,23] */ 
    int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */ 
    int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */ 
    int tm_year; /* 年份,其值等于实际年份减去1900 */ 
    int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */ 
    int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */ 
    int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/ 
    }; 
    #define _TM_DEFINED 
    #endif 
    ANSI C标准称使用tm结构的这种时间表示为分解时间(broken-down time)。 
    而日历时间(Calendar Time)是通过time_t数据类型来表示的,用time_t表示的时间(日历时间)是从一个时间点(例如:1970年1月1日0时0分0秒)到此时的秒数。在time.h中,我们也可以看到time_t是一个长整型数: 
    #ifndef _TIME_T_DEFINED 
    typedef long time_t; /* 时间值 */ 
    #define _TIME_T_DEFINED /* 避免重复定义 time_t */ 
    #endif 
    大 家可能会产生疑问:既然time_t实际上是长整型,到未来的某一天,从一个时间点(一般是1970年1月1日0时0分0秒)到那时的秒数(即日历时间) 超出了长整形所能表示的数的范围怎么办?对time_t数据类型的值来说,它所表示的时间不能晚于2038年1月18日19时14分07秒。为了能够表示 更久远的时间,一些编译器厂商引入了64位甚至更长的整形数来保存日历时间。比如微软在Visual C++中采用了__time64_t数据类型来保存 日历时间,并通过_time64()函数来获得日历时间(而不是通过使用32位字的time()函数),这样就可以通过该数据类型保存3001年1月1日 0时0分0秒(不包括该时间点)之前的时间。 
    在time.h头文件中,我们还可以看到一些函数,它们都是以time_t为参数类型或返回值类型的函数: 
    double difftime(time_t time1, time_t time0); 
    time_t mktime(struct tm * timeptr); 
    time_t time(time_t * timer); 
    char * asctime(const struct tm * timeptr); 
    char * ctime(const time_t *timer); 
    此外,time.h还提供了两种不同的函数将日历时间(一个用time_t表示的整数)转换为我们平时看到的把年月日时分秒分开显示的时间格式tm: 
    struct tm * gmtime(const time_t *timer); 
    struct tm * localtime(const time_t * timer); 
    通 过查阅MSDN,我们可以知道Microsoft C/C++ 7.0中时间点的值(time_t对象的值)是从1899年12月31日0时0分0秒到该 时间点所经过的秒数,而其它各种版本的Microsoft C/C++和所有不同版本的Visual C++都是计算的从1970年1月1日0时0分0秒 到该时间点所经过的秒数。 
    4.与日期和时间相关的函数及应用 
    在本节,我将向大家展示怎样利用time.h中声明的函数对时间进行操作。这些操作包括取当前时间、计算时间间隔、以不同的形式显示时间等内容。 
    4.1 获得日历时间 
    我们可以通过time()函数来获得日历时间(Calendar Time),其原型为: 
    time_t time(time_t * timer); 
    如 果你已经声明了参数timer,你可以从参数timer返回现在的日历时间,同时也可以通过返回值返回现在的日历时间,即从一个时间点(例如:1970年 1月1日0时0分0秒)到现在此时的秒数。如果参数为空(NUL),函数将只通过返回值返回现在的日历时间,比如下面这个例子用来显示当前的日历时间: 
    运行的结果与当时的时间有关,我当时运行的结果是: 
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main(void) 

        time_t lt; 
        lt =time(NULL); 
        printf("The Calendar Time now is %d\n",lt); 
        return 0; 

    The Calendar Time now is 1122707619 
    其中1122707619就是我运行程序时的日历时间。即从1970年1月1日0时0分0秒到此时的秒数。 
    4.2 获得日期和时间 
    这里说的日期和时间就是我们平时所说的年、月、日、时、分、秒等信息。从第2节我们已经知道这些信息都保存在一个名为tm的结构体中,那么如何将一个日历时间保存为一个tm结构的对象呢? 
    其中可以使用的函数是gmtime()和localtime(),这两个函数的原型为: 
    struct tm * gmtime(const time_t *timer); 
    struct tm * localtime(const time_t * timer); 
    其 中gmtime()函数是将日历时间转化为世界标准时间(即格林尼治时间),并返回一个tm结构体来保存这个时间,而localtime()函数是将日历 时间转化为本地时间。比如现在用gmtime()函数获得的世界标准时间是2005年7月30日7点18分20秒,那么我用localtime()函数在 中国地区获得的本地时间会比世界标准时间晚8个小时,即2005年7月30日15点18分20秒。下面是个例子: 
    //本地时间,世界标准时间
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main(void) 

        struct tm *local; 
        time_t t; 
        t=time(NULL); 
        local=localtime(&t); 
        printf("Local hour is: %d:%d:%d\n",local->tm_hour,local->tm_min,local->tm_sec); 
        local=gmtime(&t); 
        printf("UTC hour is:  %d:%d:%d\n",local->tm_hour,local->tm_min,local->tm_sec); 
        return 0; 

    运行结果是:  
    Local hour is: 23:17:47
    UTC hour is: 15:17:47
    4.3 固定的时间格式 
    我们可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,两者的返回值都是char*型的字符串。返回的时间格式为: 
    星期几 月份 日期 时:分:秒 年\n\0 
    例如:Wed Jan 02 02:03:55 1980\n\0 
    其中\n是一个换行符,\0是一个空字符,表示字符串结束。下面是两个函数的原型: 
    char * asctime(const struct tm * timeptr); 
    char * ctime(const time_t *timer); 
    其 中asctime()函数是通过tm结构来生成具有固定格式的保存时间信息的字符串,而ctime()是通过日历时间来生成时间字符串。这样的 话,asctime()函数只是把tm结构对象中的各个域填到时间字符串的相应位置就行了,而ctime()函数需要先参照本地的时间设置,把日历时间转 化为本地时间,然后再生成格式化后的字符串。在下面,如果t是一个非空的time_t变量的话,那么: 
    printf(ctime(&t)); 
    等价于: 
    struct tm *ptr; 
    ptr=localtime(&t); 
    printf(asctime(ptr)); 
    那么,下面这个程序的两条printf语句输出的结果就是不同的了(除非你将本地时区设为世界标准时间所在的时区): 
    //本地时间,世界标准时间
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main(void) 

        struct tm *ptr; 
        time_t lt; 
        lt =time(NULL); 
        ptr=gmtime(&lt); 
        printf(asctime(ptr)); 
        printf(ctime(&lt)); 
        return 0; 

    运行结果: 
    Sat Jul 30 08:43:03 2005 
    Sat Jul 30 16:43:03 2005 
    4.4 自定义时间格式 
    我们可以使用strftime()函数将时间格式化为我们想要的格式。它的原型如下: 
    size_t strftime( 
    char *strDest, 
    size_t maxsize, 
    const char *format, 
    const struct tm *timeptr 
    ); 
    我们可以根据format指向字符串中格式命令把timeptr中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。 
    函 数strftime()的操作有些类似于sprintf():识别以百分号(%)开始的格式命令集合,格式化输出结果放在一个字符串中。格式化命令说明串 strDest中各种日期和时间信息的确切表示方法。格式串中的其他字符原样放进串中。格式命令列在下面,它们是区分大小写的。 
    %a 星期几的简写 
    %A 星期几的全称 
    %b 月分的简写 
    %B 月份的全称 
    %c 标准的日期的时间串 
    %C 年份的后两位数字 
    %d 十进制表示的每月的第几天 
    %D 月/天/年 
    %e 在两字符域中,十进制表示的每月的第几天 
    %F 年-月-日 
    %g 年份的后两位数字,使用基于周的年 
    %G 年分,使用基于周的年 
    %h 简写的月份名 
    %H 24小时制的小时 
    %I 12小时制的小时 
    %j 十进制表示的每年的第几天 
    %m 十进制表示的月份 
    %M 十时制表示的分钟数 
    %n 新行符 
    %p 本地的AM或PM的等价显示 
    %r 12小时的时间 
    %R 显示小时和分钟:hh:mm 
    %S 十进制的秒数 
    %t 水平制表符 
    %T 显示时分秒:hh:mm:ss 
    %u 每周的第几天,星期一为第一天 (值从0到6,星期一为0) 
    %U 第年的第几周,把星期日做为第一天(值从0到53) 
    %V 每年的第几周,使用基于周的年 
    %w 十进制表示的星期几(值从0到6,星期天为0) 
    %W 每年的第几周,把星期一做为第一天(值从0到53) 
    %x 标准的日期串 
    %X 标准的时间串 
    %y 不带世纪的十进制年份(值从0到99) 
    %Y 带世纪部分的十进制年份 
    %z,%Z 时区名称,如果不能得到时区名称则返回空字符。 
    %% 百分号 
    如果想显示现在是几点了,并以12小时制显示,就象下面这段程序: 
    //显示现在是几点了,并以12小时制显示
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main(void) 

        struct tm *ptr; 
        time_t localTime; 
        char str[80]; 
        localTime=time(NULL); 
        ptr=localtime(&localTime); 
        strftime(str,100,"It is now %I %p\n",ptr); 
        printf(str); 
        return 0; 

    其运行结果为: 
    It is now 4PM 
    而下面的程序则显示当前的完整日期: 
    //显示当前的完整日期
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    void main( void ) 

        struct tm *newtime; 
        char tmpbuf[128]; 
        time_t localTime1; 
        time( &localTime1 ); 
        newtime=localtime(&localTime1); 
        strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime); 
        printf(tmpbuf); 

    运行结果: 
    Today is Saturday, day 30 of July in the year 2005. 
    4.5 计算持续时间的长度 
    有时候在实际应用中要计算一个事件持续的时间长度,比如计算打字速度。在第1节计时部分中,我已经用clock函数举了一个例子。Clock()函数可以精确到毫秒级。同时,我们也可以使用difftime()函数,但它只能精确到秒。该函数的定义如下: 
    double difftime(time_t time1, time_t time0); 
    虽然该函数返回的以秒计算的时间间隔是double类型的,但这并不说明该时间具有同double一样的精确度,这是由它的参数觉得的(time_t是以秒为单位计算的)。比如下面一段程序: 
    //计算持续时间的长度 
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main(void) 

        time_t start,end; 
        start = time(NULL); 
        system("pause"); 
        end = time(NULL); 
        printf("The pause used %f seconds.\n",difftime(end,start));//<- 
        system("pause"); 
        return 0; 

    运行结果为: 
    请按任意键继续. . . 
    The pause used 2.000000 seconds. 
    请按任意键继续. . . 
    可以想像,暂停的时间并不那么巧是整整2秒钟。其实,你将上面程序的带有“//<-”注释的一行用下面的一行代码替换: 
    printf("The pause used %f seconds.\n",end-start); 
    其运行结果是一样的。 
    4.6 分解时间转化为日历时间 
    这里说的分解时间就是以年、月、日、时、分、秒等分量保存的时间结构,在C/C++中是tm结构。我们可以使用mktime()函数将用tm结构表示的时间转化为日历时间。其函数原型如下: 
    time_t mktime(struct tm * timeptr); 
    其返回值就是转化后的日历时间。这样我们就可以先制定一个分解时间,然后对这个时间进行操作了,下面的例子可以计算出1997年7月1日是星期几: 
    //计算出1997年7月1日是星期几 
    /* Date : 10/24/2007 */
    /* Author: Eman Lee  */
    #include "stdio.h" 
    #include "stdlib.h" 
    #include "time.h" 
    int main(void) 

        struct tm time; 
        time_t t_of_day; 
        time.tm_year=1997-1900; 
        time.tm_mon=6; 
        time.tm_mday=1; 
        time.tm_hour=0; 
        time.tm_min=0; 
        time.tm_sec=1; 
        time.tm_isdst=0; 
        t_of_day=mktime(&time); 
        printf(ctime(&t_of_day)); 
        return 0; 

    运行结果: 
    Tue Jul 01 00:00:01 1997 
    现在注意了,有了mktime()函数,是不是我们可以操作现在之前的任何时间呢?你可以通过这种办法算出1945年8月15号是星期几吗?答案是否定的。因为这个时间在1970年1月1日之前,所以在大多数编译器中,这样的程序虽然可以编译通过,但运行时会异常终止。
Open Toolbar