qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

如何从程序员转型为项目经理

  当你预期的那一天,也许是你害怕的那一天,终于来到了:从工程师的队伍里,你被提拔到了软件项目领导或者团队领导即项目经理的位置。
  这也许就是你选择的职业道路,或许你不太情愿,将就尝试一下。无论在哪种情况下,你都可能缺少工程学科、人员管理以及领导能力的相关教育。这需要更多的领导能力和管理(它们不是一回事),而不能象Dilbert(译注:著名IT漫画主角)那样简单地和老板对抗了。
  当你考虑新的目标时,请考虑下面的活动计划列表。一次就抓住了每个亮点,这是不可能的。但是这份建议说明可以帮助你将注意力放在可以提高你和你的团队绩效的活动上。
  一、建立优先级
  作为项目经理,首先要做的、最重要的事是你需要有意识地建立优先级。当你仍陷于繁重的软件开发活动中时,你需要一套新的职责。过多的经理新手不能抗拒技术的吸引而陷于此类活动,这将导致项目组的其他人员想要获得经理的帮助时,却得不到帮助。
  有成效的领导知道他们首要的任务是为其他组员提供服务。这些服务包括训练和指导、解决问题和冲突、提供资源、建立项目目标和优先级、提供适当的技术指引。
  要使每个组员都能清楚的知道,你总是可以帮助他们。我发现将自己定位于为被我监督的人工作是非常有意义的,而不是相反的。在你所作的事情中,对于组员要求你帮助他们这件事,应该具有非屏蔽中断的优先级。
  第二重要的,是使你的客户满意。作为一名经理,没有直接的能力使客户满意,因为你已不再是作为个人提供产品和服务完成这点。相反,你必须建立一种环境,准许你的组员最大程度上满足客户的需求。经理提供了强有力的方法,有效地提高客户的满意度。
  第三重要的,是为你的项目工作。因为也许还有其他许多技术上的项目,或者其他经理的请求帮助,诸如为指导委员会工作。当这些和二个高级别的发生冲突时,都要准备推辞掉。很明显,使其他经理满意的事情是你最不重要的事情。
  在一个有秩序的组织里,如果你在三个以上的重大环节上获得了成功,其他的经理都会很激动的。我们并不都能很幸运地工作在一个良好的环境里,但一定要对你任务单上排在最前面的工作任务努力尽到最大的责任。集中精力有效地、快乐地、尽可能地帮助你的组员,不要将精力放在使你上司满意的上面。
  二、分析你的技能差距
  除非你已经为新位置做好了准备,否则相对于你当前的领导能力和管理技能,你会感到一些差距。出色的技术背景或许是你被选为领导角色的一个因素,但是你要想干得出色,你需要更多的技能。针对别人的评论和项目,真实地列出你的长处和短处,然后减少差距。软件人员并不以令人满意的人际关系技能出名。你会希望增强处理人际关系的经验:解决冲突、说服以及灌输想法。你也不得不处理包括招聘、解雇、商谈计划表,以及在你的办公室里评论某人业绩使其伤心落泪等一些事务。
  我发现从一堂倾听技能课开始我的管理职业是非常好的。当作为个体提议人,积极地将我们自己的技术议程提交小组时,我们经常对此感到非常惬意。有效的管理要求更多的合作和善于接受的人际关系方式。要花点时间学习如何(何时)巧妙地引导自己的自然判断。倾听技能课提供了一种交流机制,我已经发现在许多场合下都很有用。
  接着,到讲台的另一侧,提高你的演讲能力。如果你真的不适应公开场合的讲话,学习戴尔.卡内基的课会有帮助的。你会发觉,通过这样的培训获得的经验,以及获得提高的交流能力,都可以帮助你更好地适应将来的工作。
  作为项目领导,为了计划和跟踪项目, 以及当需要项目回退而采取修正措施时,你有责任调整其他人的工作。参加项目管理的培训课,阅读一些有关项目和风险管理的书籍和文章。参加项目管理学会,阅读其月刊--PM Network。SEI的软件能力成熟度模型对于软件项目计划和项目跟踪提供了很多有用的建议。建立优先级的能力、控制有效果的会议、清晰的交流,对于你,作为一名经理的绩效将会有实质上的影响。
  定义“质量”
  几乎每个人都会认真地对待质量问题而且都希望生产出高质量的产品。然而,对于软件的质量含义,没有一个统一的定义。传统上的软件质量观点和“足够好”的软件观点有着激烈的争论。为了帮助小组走向成功,需要花一些时间和你的组员、客户共同探讨质量的含义。 这两种阵营在思想上经常不会有相同的定义,可以很容易的就不同目的开展工作。关注交付计划的经理对于想正常地检查每行代码的工程师会不耐烦的;认为可靠性非常重要的客户对一个带有很少使用但带有很多bugs的特性的产品是不会满意的;一个很好的GUI也许会让用户厌烦,因为用户已经熟记了如何有效地使用前一个版本的产品。
  为了更好的理解客户对软件质量的看法,在Kodak,我的小组曾经邀请了我们的客户和他们的经理就这个议题在一个开放的论坛展开讨论。这个论坛是很有意义的,那些使用我们产品的人有着自己的理解,通过讨论,我们可以知道我们制定质量的思路有哪些和他们是不相符的。明白了不同,就可以使你集中精力,照顾客户的最大利益,而不是使开发人员获得最大满意。
  软件质量的传统描述包括要与说明书一致,满足客户的需求,代码和文档没有缺陷。“六个∑质量” (six-sigma quality)这个流行词,建立了一个非常高的尺度,用于监测失败的频率和密度。但它不适用于如快速产品交付,可用性,充足的特性集,已支付价钱的交付意义这样的质量尺度,。对于我们生产和购买的产品,我们总是热衷于尽可能涵盖所有的这些质量特性,然而,妥协总是必须的。
  在一个项目的需求阶段,我们制定了包括十项质量属性的一个列表,如效率,协同性,正确性以及宜于学习,我们认为这对于用户来说是最重要的。我们请客户关键人物代表小组以1到5的尺度评估每项属性。一旦我们决定了哪些属性是最重要的,我们就可以设计并实现这些目标。如果你在了解了对于客户的质量含义并在设计实现质量属性的过程中没有麻烦的话,而且客户对质量属性表示满意,那你是很幸运的。在众多关注的质量说明中,我曾听到过一个:“客户回来了,但产品没有” 。和你的客户、开发人员一起对每一个产品都确定适当的质量目标。一旦决定了,就给出达到质量目标的明确的最高优先级。以身作则,按很高的质量标准要求你自己的工作。采用这个座右铭:“力求尽善尽美,满足于优秀。”
  三、表彰成绩
  对你组员成绩的表彰和奖励,是激励他们的一种很重要的手段。除非你的小组中已经有了一种表彰程序,否则这应是你最重要的事情之一。表彰包括象征性的东西(证书,旅游奖励)以及实际的东西(电影票,餐馆礼品券,兑现奖)。在送赠品时要说一些亲切的话语:“感谢你所给予的帮助”或者“祝贺取得了成绩”。在表彰和奖励上花费很少的心思和钱,就可以获得很多的友好和将来的合作。包括客户代表,以及为项目成功做出过贡献的支持人员等等开发组外的人员也可以获得表彰。
  和你的组员讨论,了解他们
  感兴趣的表彰和奖励的方式。使得无论大小成就的表彰活动成为小组文化的一个标准组成部分。对每位组员对其所作的工作表现出发自内心的兴趣也要给与含蓄的表扬,为消除所有影响他们战斗力的障碍尽你的力量。表彰是展示组员以及小组外的其他人的一种方式――你要知道并感谢他们为小组成功所作的贡献。
 四、学习过去
  你的小组在过去承担的一些项目有可能没有取得完全的成功。甚至在成功的项目上,我们也能经常认为一些事情我们下次会作得更好。当你进入了新的领导角色,需要花点时间了解早期的项目为什么失败,并要计划避免犯同样的错误。对于软件开发,每位经理花时间处理每种可能要发生的错误是非常困难的,学习过去的成功和失败就是个成功的开始。
  可以从过去你们小组承担的一个没有经过检查评估的项目着手,不要管其成功还是失败,实施项目后的回顾(有时称作事后调查分析)。你的目标不是判定责任,而是为了在将来项目中作得更好。借此,可以了解什么已经作得很好,什么应该作得更好。在当前每个项目的主要里程碑时,通过集体讨论或公平的组织者,用同样的方式,领导小组用头脑风暴的方式对其展开分析。
  另外,要了解领悟已有的软件工业的最佳准则。一个好的起点是Steve McConnell的Jolt Award获奖作品:快速开发(Rapid Development,Microsoft Press, 1996)的第三部分,叙述了27个最佳准则。也要避免McConnell叙述的36个常见的软件开发错误。你的组员也许反对新的工作方式,但是你的角色是作为一名领导,要确保团队一致连续地使用最佳可用的方法、过程和工具。积极促进组员之间的信息共享,这样局部单个最好的实践经验就能成为每个开发人员的工具箱的一部分。
  五、建立改进目标
  一旦你对过去的项目建立起了回顾,确立了质量对小组的意义,你就要建立短期以及长期改进的一些目标。目标要尽可能量化,所以你要划分几个简单的阶段,标明你是否采取了适当的过程朝着目标前进。
  例如,如果你认定由于需求的不稳定导致项目经常延期,你可以建立一个改进需求稳定的目标,在6个月内提高50%。这样一个目标需要你确切知道每周或每月需求的变化数,清楚他们的出处,采取行动控制那些变更。这可能要求你要改变与那些提交需求改变的人的交流方式。
  你的目标和阶段是软件过程改进程序的组成部分,你要使之有序。作为缺乏创造力的官僚主义的最后避难所,轻视“过程”很流行。虽然事实上,每个小组都能找到改进其工作的方式。当然,如果你总是用已有的工作方式工作,你也就不要期望你会得到比以前更好的结果。有两个强烈的原因要求改进过程:校正问题,防止问题。确保你的改进努力要围绕着已知的或可预知的可能威胁项目成功的问题。领导你的小组找出当前正在使用的方法的长处和短处,以及项目面临的风险。
  我的小组召开了一次“两段式头脑风暴”练习,来确定改进软件生产力和质量过程的绊脚石。在第一次会议中,参会者在便条上写出他们关于会议主题的想法,一个便条一个想法。组织者将他们写在便条上的想法收集上来并分组。最后,我们就会得到一打主要的分类,并将其记录到活动挂图上。
  第二次会议,相同的参会者在便笺上写出解决这些障碍的思路,并贴在挂图的合适位置。进一步细化,归纳出一些详细的活动,就可以成为我们努力的一部分,清除障碍,帮助组员实现软件的质量和生产力的目标。
  建立可度量和可达到的目标,便于你集中精力实现改进。要使目标具有明显的优先级,并可周期性地监视过程。记住你的目的是,提高你的项目和公司完成的技术和业务上成功,不要满足于一些过程改进书籍里提到的期望细节。要把改进的工作视为迷你项目,具有可分发、资源、计划和有责任的小项目。否则,过程改进活动将总处于比诱人的技术工作低的优先级上。
  六、缓慢的开始
  这篇文章提供了许多建议,帮助你,一位软件经理新人,带领你的小组走向伟大的成功。在日复一日新的工作压力面前,要努力保持你的头脑清醒。
  在长时间的塑造软件开发小组的文化和习惯上,你还是个非常重要的角色。你不必一次性都作完,可以选择跟环境最相关的的几个开始。作为软件经理,除了项目要按时按照预算完成外,你要担负的责任还很多。你还要:领导技术人员,将他们形成一个具有凝聚力的团队;建立协同团队工作的环境;鼓励和奖赏高级软件工程师的实践应用;平衡来自客户、公司,组员和你自己的需求。

posted @ 2014-08-06 10:28 顺其自然EVO 阅读(173) | 评论 (0)编辑 收藏

java逻辑运算符

  ava中的逻辑运算符包括逻辑与&,逻辑或|,逻辑非!逻辑异或^,除此之外还有几个比较相似的&&短路与,||短路或。
  那么这几个逻辑运算符到底有什么意思呢?下面我们来看看
  首先看逻辑与&的用法,只有两个都为真,结果为真,如果看如下代码
  int a = 20;
  int b = 5;
  if(a>10&b>10){
  System.out.println("true");
  }else{
  System.out.println("false");
  }
  输出false
  同样|,只要有一个为真就是真
  if(a>10|b>10){
  System.out.println("true");
  }else{
  System.out.println("false");
  }
  输出true
  !的作用是取反
  boolean a = true;
  if(!a){
  System.out.println("true");
  }
  接下来再看看短路与&&和短路或||
  int a = 10;int b = 20;
  if(a>10&&b++>10){
  System.out.println(true)
  }
  System.out.println(b);
  看看b的值是多少呢,这个时候很多人会答错,b的值最终还是20
  在这里由于第一个a>10为false,所以这个表达式为false,这样就不会执行后面的b++操作了,相当于把b++给短路了,所以叫短路与。同样短路或的作用是如果第一个为真,那么整个表达就为true,就把第二个表达式短路了。所以叫短路或。

posted @ 2014-08-06 10:28 顺其自然EVO 阅读(210) | 评论 (0)编辑 收藏

项目管理之产品需求确认

 把今天早上我在物联网研究院参与的作业宝产品需求确认的过程大致叙述一下,为将来即将走上软件开发工作岗位的同学揭开项目管理的神秘面纱。
  先说说项目背景吧。因为,该软件产品还没有上线,涉及到商业机密,所以我只能大致说明一下,这是一款智能手机上的本地程序,中小学生可以在手机上提交作业,教师在后台评判作业,学生可以浏览作业的评判结果。
  项目组采用的项目管理方法论主要是基于scrum敏捷开发,迭代或冲刺的周期为两周。因为一些客观原因,项目的某些方面没有完全严格按照scrum来实施,例如:我们这里没有明确谁是PO和SM,当然这种情况一般老板就是PO和SM,项目毕竟总要有人负责嘛。
  需求确认是每个迭代前的重要项目管理活动,今天早上主要做了这件事情,下面就说说这个过程,至于项目管理的其他方面,以后工作中碰到了,再抽时间整理成文。
  早上8点半产品组内部进行了v0.4版本的范围确定,当然功能点不是用story描述的,所以说不是严格的scrum,基本上确认的是一个功能清单。产品组内部确认完成后,9点产品组和开发组的负责人及工程师在会议室就v0.4版本中的功能清单逐条评审。评审的过程由产品组逐条讲解功能,开发组的软件工程师确认每个功能技术实现的可行性和开发工期上的可行性。对v0.4功能范围达成共识后,产品组会后细化v0.4中的每个功能项,给出界面原型图和功能描述,提交到redmine上。开发组组长根据redmine上的功能描述,在redmine上创建相应的开发任务指派到开发人员身上,一个冲刺就定义完成了,测试组根据功能描述准备相应的测试案例。

posted @ 2014-08-06 10:27 顺其自然EVO 阅读(196) | 评论 (0)编辑 收藏

TestNG测试带参构造函数的类

今天被同事问到一个问题,问题描述如下:
  一个测试类,只有一个带参构造函数。在带参构造函数上加@Test,同时加@Parameters注解从testng.xml中传递参数。为保证测试函数在带参构造函数之后执行,所以测试方法前的@Test加了dependsOnMethods属性,依赖于带参构造函数。
  重现问题的示例代码如下:
package com.ibm.testng.test;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class WebTest {
//Times staying on the server
private int stayTime;
//Constructor with params
@Test
@Parameters({"stayTime"})
public WebTest(int stayTime) {
System.out.println("Constructor with parameter!");
this.stayTime = stayTime;
}
@Test(dependsOnMethods="WebTest")
public void stayOnServer() {
System.out.println("The times staying on server: " + stayTime);
}
}
  输出结果:
  根据输出结果可知,错误原因是没有找到stayOnServer()依赖的测试函数WebTest()。可能会疑问,不是有名称为WebTest()的函数吗,而且还用@Test注解了,为什么会提示找不到呢?
  这个错误,跟TestNG的执行原理有关。TestNG启动之后,先调用构造函数创建所有的测试实例,然后才进行测试。因此,构造函数与测试函数的执行时机不一样,构造函数在所有测试方法之前先执行,没有必要再通过@Test的dependsOnMethods属性使测试函数依赖于构造函数。
.  构造函数没必要用@Test注解(注解了也不会报错),但是TestNG不会把它当做测试函数,它也不会和其他测试函数一起执行。可能习惯性地认为带参构造函数前的@Parameters一定要和@Test一起使用,其实不是这样的,@Parameters可以放的位置有如下两种情况:
  1. 任何已经被@Test,@Factory或者Configuration annotation(@BeforeXXX/@AfterXXX)注解的函数。
  2. 测试类中至多一个构造函数前面。TestNG会调用该构造函数创建测试实例,并从testng.xml中获得该构造函数需要的参数。
  可能你希望使用某个构造函数来创建测试实例,但是TestNG会根据自己的规则选择构造函数。TestNG选择构造函数的规则:
  1. 通常情况下,会选择默认无参构造函数或者自己添加的无参构造函数。
  2. 如果有带参构造函数,且被@Parameters注解,就会选择该带参构造函数。
  3. 如果同时有无参构造函数和带参构造函数,且带参构造函数没有被@Parameters注解,选择无参构造函数。
  4. 如果只有带参构造函数,但是带参构造函数没有被@Parameters注解,执行测试函数时抛出org.testng.TestNGException。
  对于带参构造函数的测试类,使用@Factory注解,不仅可以解决带参构造函数没有被@Parameters注解而导致的org.testng.TestNGException,而且还可以充分发挥TestNG参数化测试的优势。以添加如下@Factory注解的代码为例:
@Factory
public static Object[] create() {
System.out.println("Create test objects!");
List<WebTest> objectList = new ArrayList<WebTest>();
for(int i=1; i<4; i++) {
objectList.add(new WebTest(i*10));
}
return objectList.toArray();
}
  上面代码会创建3个stayTime分别为10,20,30的测试实例。如果使用@Parameters注解,必须创建3个test分别将10,20,30从testng.xml传入。因此,@Factory为带参构造函数的类创建一系列有规律的测试实例提供了便利。

posted @ 2014-08-06 10:16 顺其自然EVO 阅读(294) | 评论 (0)编辑 收藏

QTP-MySql+对象库实例

  首先QTP要连接MySql 先确保机器上有MySql的数据源 没有的话去网上下一个装上把。
  我这里用的是Mysql 5.1的数据源 ,装完后,在桌面新建一个TXT文档,然后修改后缀改为udl,就变成了数据链接这样子,打开它,你会发现《提供程序》内就没有Mysql这个名字的程序 ,但是在windows的管理工具数据源内能找Mysql 5.1的名字也可以添加,后来找了好久才知道原来Mysql在数据链接内是叫 Miceosoft OLE DB Provider for ODBC Drivers 这个名字。
  现在找到了名字 接下来就是设置《连接》的属性,数据源名称可以随意填写,下面的用户名和密码就需要MySql的管理人员给权限。当都设置好了,点击测试连接,显示连接成功的话就是能正常启动了。
  上面配置好了以后,我们用记事本的方式打开*.udl,里面有这些内容 我们只需要复制红线那部分,这部分为链接地址
  好了,接下来就进入编写阶段了
  实现功能
1:读取数据库 USER_ 表内的 SCREEN 和 SEREENNAME 这两列下含有"test_"字符串的数据,
2:循环写入一个登陆界面,实现正确登陆
3:验证点,登陆完毕后主界面会有一个对象内显示 Welcome test01! ,用描述性编程找到该对象获取其中我所需要的属性值进行验证
Dim conn
Dim name
Dim sql
Dim suu
Dim inn '检查字段
SystemUtil.Run "http://192.168.0.233/web/guest/home"
'这一段就是复制当时记事本里的那一段语句 这段语句有个问题就是 自己要手动往里添加用户密码噢 所以我再里面加了一个Password=1111
Mysql="Provider=MSDASQL.1;Persist Security Info=False;User ID=root;Password=1111;Data Source=sqltest"
'select screenName,screenName from user_ where screenName like 'test__';
'这段话表示说 搜索数据库内 USER_ 表内 screenName,screenName 这2个列里面所有包含 test 的数据
sql="select screenName,greeting from user_ where screenName like 'test__';"
Set conn=CreateObject("ADODB.CONNECTION")
conn.Open Mysql
If conn.State<>0 Then
Reporter.ReportEvent micPass,"连接成功","连接成功"
else
Reporter.ReportEvent mimicFail,"连接失败","连接失败"
End If
Set res=CreateObject("ADODB.Recordset")
res.Open sql,conn,1,1 '1,1表示只读;1,3表示插入数据;2,3表示修改数据
res.MoveFirst'使游标指向第一个记录
sum=""
'res.EOF表示游标到达最后一行
While Not res.EOF
'读取整个表内的所有数据
'    For i=0 to res.Fields.Count-1'str.Fields.Count表示字段个数
'     sum=sum& res(i) & " " '把整个记录显示出来
'   Next
'获取数据库内 screenName 列的每一行数据
sum=res("screenName")
'截取字符串内 从左到右4位字符
suu=Left(sum,4)
If suu = "test" Then
'检查字段变量
inn=res("greeting")
'录制登陆过程 把账号密码做参数化
Browser("测试比对样品 - 登录").Page("测试比对样品 - 登录").WebEdit("_58_login").Set sum @@ hightlight id_;_Browser("测试比对样品 - 登录").Page("测试比对样品 - 登录").WebEdit(" 58 login")_;_script infofile_;_ZIP::ssf1.xml_;_
Browser("测试比对样品 - 登录").Page("测试比对样品 - 登录").WebEdit("_58_password").set"1111" @@ hightlight id_;_Browser("测试比对样品 - 登录").Page("测试比对样品 - 登录").WebEdit(" 58 password")_;_script infofile_;_ZIP::ssf2.xml_;_
Browser("测试比对样品 - 登录").Page("测试比对样品 - 登录").WebButton("登录").Click
'这里是使用SPY抓取获取到对象属性值,对该对象2个属性进行描述性编程 对象库内不要放入被描述的对象 ,然后使用 .GetROProperty方法获取所需要对象属性值
'这里抓取了2个对象进行描述是应为2个该对象使用1个对象进行描述时,界面上还有其他对象的属性是一样的,所以描述对象时 尽量抓取对象独有的属性,当一个属性描述找不到时,就再增加一个属性描述
nn=Browser("测试比对样品 - 稿件管理").Page("测试比对样品 - 稿件管理").WebElement("innertext:=Welcome "&sum&"!","html tag:=SPAN").GetROProperty("innerhtml")
'设置检查点
If nn=inn Then
print "nn="&nn&"   inn="&inn
Reporter.ReportEvent micPass,"检查点","PASS"
else
Reporter.ReportEvent micFail,"检查点","Ng"
End If
Browser("测试比对样品 - 稿件管理").Page("测试比对样品 - 稿件管理").Link("text:=退出").Click
End If
'Print sum & vbCRLF'打印所有查询的记录   VBCRLF 换行语句
res.MoveNext'使游标进入下一个
Wend
@@ hightlight id_;_Browser("测试比对样品 - 稿件管理").Page("测试比对样品 - 稿件管理").Link("退出")_;_script infofile_;_ZIP::ssf6.xml_;_
  报告显示结果

posted @ 2014-08-06 10:01 顺其自然EVO 阅读(219) | 评论 (0)编辑 收藏

测试VDI网络性能 保证终端用户体验

 如果不检查,虚拟桌面基础架构(VDI)可能会显著增加网络压力,从而直接影响应用程序的性能及终端用户的体验。但是,如何知道VDI是否获得了足够的网络带宽呢?以下方法可以确定VDI的网络性能。
  VDI应用程序性能:对终端用户体验执行基准测试
  无论您的基准测试软件提供了何种统计信息,总体性能中最重要的一部分是终端用户体验。终端用户不关心您的VDI系统,他们只要求系统比以前更好更快。
  如果网络流量过载,或者后台VDI服务器过载,那么应用程序性能就会下降,而终端用户体验也会随之变差。在一些极端情况中,用户敲击键盘到屏幕显示字母的延迟时间可能会达到1至2秒钟。
  因此,量化终端用户体验的最佳方法之一是对比VDI环境与独立PC的应用程序加载时间。例如,您可以对比两个环境的MicrosoftWord启动时间。用户可能不会注意到几秒钟的差别,但是相差5秒钟以上,那么您就必须采取措施优化基础架构性能。
  您还可以通过执行一些计算密集型任务来测试终端用户体验。例如,如果财务部门定期执行一个复杂报表,那么您可以比较它在虚拟桌面和在独立PC上的任务执行时间。
  无论是否对终端用户体验进行基准测试,都一定要考虑网络负载和延迟的影响。在上午9:00上班时间执行基准测试,得到的性能数据肯定与半夜执行的结果不同。在VDI网络处于最高负载时执行基准测试,得到的测试结果肯定是最准确的。
  测定VDI性能的另一种方法是使用免费工具LoginVSI。这个工具不仅能在部署VDI时建立基准,也能够在其修改之后,测试它的效果。
  VDI网络问题:发现饱和征兆
  VDI环境产生的流量会大于普通非VDI环境。但是,VDI相关协议比其他网络协议的效率更高,所以一定要检查网络中是否出现的饱和征兆。有许多方法可以测试网络饱和状态,选择的方法取决于具体的基础架构。使用Ping测试VDI服务器的网卡是最简单的。虽然Ping一般是用于检查丢包状态,但是这个工具也能反映响应时间。Ping信息用于判断网络延迟时间。而Tracert也有相似的作用。
  如果VDI服务器运行的是Windows系统,那么可以使用性能监视器查看每个网卡的进出流量。然而,使用这种方法需要注意两个问题。首先,由于数据包大小不一,因而发送和接收数据包的数量不重要。您需要关注的是发送和接收的字节数。其次,一定要记住,如果采集数据的频率过密,性能监视器可能会对系统性能产生负面影响。
  SNMP是另一种测试网络饱和状态的方法。许多网络交换机都内置了SNMP监控功能,可用于检查网络运行性能。
  无论使用哪一种方法检查网络的饱和状态,都有很多网络路径需要分析。首先检查VDI客户端与VDI前端服务器(一般为负载均衡器)之间的路径。其次检查VDI前端和VDI后端之间的链路。由于VDI基础架构的创建方式不同,这可能并不简单。最后要检查的是宿主服务器与存储架构之间的链路。
  根据遇到的问题,您可能需要对网络流量进行优先级划分,或者升级网络负载均衡。此外,提高VDI服务器与存储基础架构之间的网络速度也可能会有所帮助。

posted @ 2014-08-06 10:00 顺其自然EVO 阅读(234) | 评论 (0)编辑 收藏

Java 代理(proxy)模式

代理模式(Proxy Pattern)
  代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
  如下列子:
package proxy;
interface Dao{
public void insert();
}
class JdbcDao implements Dao{
public void insert(){
System.out.println("in jdbc insert");
}
}
class HibernateDao implements Dao{
public void insert(){
System.out.println("in hibernate insert");
}
}
class ProxyDao implements Dao{
private Dao dao;
public ProxyDao(Dao dao){
this.dao=dao;
}
public void insert() {
System.out.println("write log before invoke");
dao.insert();
System.out.println("write log after invoke");
}
}
public class Test {
public static void main(String[] args) {
Dao jdbcDao =new JdbcDao();
Dao proxydao = new ProxyDao(jdbcDao);
proxydao.insert();
}
}
  运行结果:
  write log before invoke
  in jdbc insert
  write log after invoke
  随着Proxy的流行,Sun把它纳入到JDK1.3实现了Java的动态代理。动态代理和普通的代理模式的区别,就是动态代理中的代理类是由 java.lang.reflect.Proxy类在运行期时根据接口定义,采用Java反射功能动态生成的。和 java.lang.reflect.InvocationHandler结合,可以加强现有类的方法实现。如图2,图中的自定义Handler实现 InvocationHandler接口,自定义Handler实例化时,将实现类传入自定义Handler对象。自定义Handler需要实现 invoke方法,该方法可以使用Java反射调用实现类的实现的方法,同时当然可以实现其他功能,例如在调用实现类方法前后加入Log。而Proxy类根据Handler和需要代理的接口动态生成一个接口实现类的对象。当用户调用这个动态生成的实现类时,实际上是调用了自定义Handler的 invoke方法。
  Proxy类提供了创建动态代理类及其实例的静态方法。
  (1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下:
  public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException
  参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。
  (2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下:
  public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws
  IllegalArgumentException
  参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口,参数handler 指定与动态代理类关联的 InvocationHandler 对象。
  以下两种方式都创建了实现Foo接口的动态代理类的实例:
  /**** 方式一 ****/
  //创建InvocationHandler对象
  InvocationHandler handler = new MyInvocationHandler(...);
  //创建动态代理类
  Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
  //创建动态代理类的实例
  Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
  newInstance(new Object[] { handler });
  /**** 方式二 ****/
  //创建InvocationHandler对象
  InvocationHandler handler = new MyInvocationHandler(...);
  //直接创建动态代理类的实例
  Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);
  由Proxy类的静态方法创建的动态代理类具有以下特点:
  动态代理类是public、final和非抽象类型的;
  动态代理类继承了java.lang.reflect.Proxy类;
  动态代理类的名字以“$Proxy”开头;
  动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;
  Proxy 类的isProxyClass(Class<?> cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类;
  动态代理类都具有一个public 类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。
  由Proxy类的静态方法创建的动态代理类的实例具有以下特点:
  1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:
  (Foo) foo //合法
  2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。
  3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。
  InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:
  Object invoke(Object proxy,Method method,Object[] args) throws Throwable
  参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args 指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。
  最后看一个例子,该例子模仿spring 的AOP原理。
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class Logic{
public void logic(){
Dao dao = Factory.create();
System.out.println("dynamic proxy's name: "+dao.getClass().getName());
dao.insert();
}
}
class Factory{
static Dao create(){
Dao dao = new JdbcDao();
MyInvocationHandler hand = new MyInvocationHandler();
return (Dao)hand.get(dao);
}
}
interface Dao{
public void update();
public void insert();
}
class JdbcDao implements Dao{
public void update(){
System.out.println("in jdbc update");
}
public void insert(){
System.out.println("in jdbc insert");
}
}
class HibernateDao implements Dao{
public void update(){
System.out.println("in hibernate update");
}
public void insert(){
System.out.println("in hibernate insert");
}
}
class MyInvocationHandler implements InvocationHandler {
Object o;
public Object get(Object o){
System.out.println("in get method of MyInvocationHandler");
this.o = o;
return Proxy.newProxyInstance(o.getClass().getClassLoader(),o.getClass().getInterfaces(),this);
}
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
System.out.println("write log before invoke");
Object result = arg1.invoke(o, arg2);
System.out.println("write log after invoke");
return result;
}
}
public class Test {
public static void main(String[] args) {
Logic l = new Logic();
l.logic();
}
}
  运行结果:
  in get method of MyInvocationHandler
  dynamic proxy's name: proxy.$Proxy0
  write log before invoke
  in jdbc insert
  write log after invoke
  结论: JDK的动态代理并不能随心所欲的代理所有的类。Proxy.newProxyInstance方法的第二个参数只能是接口数组, 也就是Proxy只能代理接口。

posted @ 2014-08-05 10:01 顺其自然EVO 阅读(198) | 评论 (0)编辑 收藏

IBM Security AppScan Glass Box:一种全新的漏洞扫描思想

  Glass Box 是 IBM Security AppScan Standard Edition(以下简称 AppScan)8.5 版本以后引进的一个新的组件,是对 AppScan 的一个比较大的改进。Glass Box 引进了运行时分析的技术,通过部署在服务器端的代理,在探索和测试阶段搜集 Web 应用程序信息,并进行分析,进而反馈给 AppScan,使 AppScan 更有针对性的进行探索和扫描,提高了扫描的精确性,并有利于发现更多的漏洞。
  Glass Box 并不仅仅是 AppScan 的一个新的特性,而是代表了一种全新的思想,将动态分析技术与传统的 AppScan 黑盒测试技术结合起来,对 Web 应用程序进行代码级别的分析,给出更精确的分析结果,从而更有效的帮助客户保护好自己的网站。
  前言
  Glass Box 是 IBM Security AppScan Standard Edition(以下简称 AppScan)8.5 版本以后引进的一个新的组件,是对 AppScan 的一个比较大的改进。Glass Box 引进了运行时分析的技术,通过部署在服务器端的代理,在探索和测试阶段搜集 Web 应用程序信息,并进行分析,进而反馈给 AppScan,使 AppScan 更有针对性的进行探索和扫描,提高了扫描的精确性,并有利于发现更多的漏洞。Glass Box 并不仅仅是 AppScan 的一个新的特性,而是代表了一种全新的思想,将动态分析技术与传统的 AppScan 黑盒测试技术结合起来,对 web 应用程序进行代码级别的分析,给出更精确的分析结果,从而更有效的帮助客户保护好自己的网站。
  本文首先简单介绍了 AppScan Glass Box 的技术架构,然后介绍了在 AppScan 8.5 中 Glass Box 在 Windows XP 下使用效果。Glass Box 支持 WebSphere、Tomcat、JBoss 等多种应用服务器,本文选择的 Web 服务器为大家常见的 Tomcat 7.0。
  技术架构
  Glass Box 可分为客户端和服务端。客户端又可分为 GlassAPI 和 Glass Box 引擎服务,GlassAPI 用于和服务器端通信,获取服务端返回的问题信息;Glass Box 引擎服务基于预定义的验证规则,对获取到的服务端进行分析,判断是否存在漏洞。服务端通过代理程序搜集服务器端信息,包括 Web 应用程序运行时信息(根据预定义的特征匹配规则)、源代码信息、配置文件信息、操作系统信息、数据库信息和 Web 服务器信息等,并将搜集到的信息返回给客户端。
  图 1. Glass Box 技术架构图
  
  配置及使用
  打开扫描配置面板,可对 Glass Box 进行配置。点击 Glass Box 面板中的添加按钮,可添加 Glass Box 代理程序。
  图 2. Glass Box 代理程序定义
  
  代理程序的用户名和密码分别为安装 Glass Box 时设定的用户名和密码,如需要修改密码,可运行 AgentCredentials.bat <username> <password> ,或直接修改位于 GBootStrap\WEB-INF 目录下的 users.xml 文件,重启 Tomcat 后生效。用户可添加多个 Glass Box 代理程序,但 AppScan 同一时间只能使用其中的一个。添加代理程序成功后,可对 Glass Box 进行设置,选中"在探索阶段使用 glass box ",可发现更多的隐藏的 URL;选中"在测试阶段使用 glass box",可发现更多的漏洞和提供更详细的漏洞信息。配置成功后,AppScan 右下角状态栏将显示"Glass box 扫描:已启用"。
  Glass Box 配置成功后,需要对 Web 应用程序重新扫描。需要注意的是,由于 Glass Box 对 URL 的解析问题,扫描本地网站需要配置虚拟域名,即起始 URL 不能是“http://localhost/myproject”, 而应该是“http://mysite/myproject”。Glass Box 目前仅支持 Java 项目。本文所选用扫描网站是 IBM AppScan 开发人员提供的 AltoroJ 项目。
  通过对配置 Glass Box 前后的扫描结果进行分析,我们分析一下使用 Glass Box 的三个优势。为方便起见,本文采用默认的扫描配置(新建一个常规扫描,采用默认的扫描策略,对扫描配置的各项参数不做任何修改),并且没有对结果进行分析,排除误报的漏洞。每次扫描,结果可能会略有不同;若差别太大,则应该检查扫描配置信息,查看日志,找出问题所在。
  1. 在探索阶段通过检测出代码中不可见的参数和 cookie 信息,探索隐藏的扫描路径,提高扫描覆盖率。
  在应用程序中,有一些参数并未暴露给用户,即对用户是"不可见"的,传统的 AppScan 运行在客户端,并不能够检测到这些参数,更无法探索到相关的页面。 Glass Box 运行于探索阶段全过程,预定义一些"感兴趣"的方法(如 getParameter、Runtime.getRuntime().exec 等),并时刻检测这些方法是否运行,并进而探索出其中的参数,再根据这个参数构造扫描路径。
  2. 在测试阶段,Glass Box 可增强 AppScan 在各种漏洞类型方面的检测。
  Glass Box 通过搜集服务端信息,可减少误报率,增强 AppScan 对各种漏洞类型的检测,主要能够增强 AppScan 对注入攻击、不安全的直接对象引用、安全配置错误和不安全的加密存储等漏洞的检测。通过扫描 AltoroJ 项目可以发现,配置 Glass Box 前,共扫描出了 100 个漏洞;而配置 Glass Box 后,共扫描到了 139 个漏洞;Glass Box 增加了了大约 40% 的漏洞扫描发现数量。下表是按照 OWASP Top 10 漏洞分类方法,对使用 Glass Box 前后的扫描漏洞数量进行的对比。
  表 1. 使用 Glass Box 前后发现的漏洞数量对比
  有时候,Web 开发人员会屏蔽错误信息,比如设置一个错误页面,发生异常时直接跳转到该页面,AppScan 无法直接从 response 信息中判断是否存在漏洞。Glass Box 通过预定义的方法,搜集服务器端的信息,从而判断是否存在漏洞。
  通过扫描我们发现,未使用 Glass Box 前,AppScan 并未检测出用户登录页面的 SQL 注入漏洞(AppScan 可检测出各种类型的漏洞,未检测出该页面的 SQL 注入漏洞属于个别情况)。我们来分析一下原因。
AppScan 在测试阶段,向登陆页面发送请求,我们假定 AppScan 将 Username 和 Password 均设置为"'",服务器返回错误信息"Syntax error: Encountered "\'" at line 1, column 63. "。由于在 Response 中并未包含 SQL 异常信息,所以 AppScan 无法判断是否存在 SQL 注入漏洞。
  图 3. 页面显示的错误信息
 
  但是如果我们写一个测试代码,可得知当我们输入单引号时,服务器端确实报了 SQL 语法错误信息,如图 4 所示。Glass Box 安装在服务器端,当它发现请求值为 g'[number]b,且包含了单引号的信息请求时,如果出现 SQL 异常错误信息,那么 Glass Box 便判断出该页面存在 SQL 注入漏洞。
  图 4.SQL 异常信息
  3. 在生成报告阶段,可提供代码级的调试信息和修复建议
  我们以 AltoroJ 项目的登陆页面为例,对比一下使用黑盒测试和使用 Glass Box 发现的漏洞的修复过程。AppScan 通过分别在 Username 和 Password 输入框中输入"4ppSc4n"和"A' OR '7659'='7659",发现了该页面存在 SQL 注入漏洞(AppScan 中称之为"SQL 注入的认证旁路")。我们根据"请求 / 响应"信息可以发现,该漏洞存在于 doLogin 这个 servlet 中,如图 5 所示。
  图 5.AppScan “请求 / 响应”
  
  我们根据 WEB-IBF/web.xml 中的信息进一步判断出漏洞存在于 LoginServlet.java 文件中。
  清单 1.web.xml 文件中的 LoginServlet 配置
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/doLogin</url-pattern>
</servlet-mapping>
<servlet>
<description>
</description>
<display-name>
LoginServlet</display-name>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>
com.ibm.rational.appscan.altoromutual.servlet.LoginServlet
</servlet-class>
</servlet>
  打开 LoginServlet.java 文件,我们依然很难一眼就判断出漏洞的准确位置,需要对代码做进一步的分析。经过分析,找到存在漏洞的语句:
  清单 2. LoginServlet.java 文件中存在漏洞的语句
  if (!DBUtil.isValidUser(username, password))
  然后,我们再找到 DBUtil 类中的 isValidUser 函数,最终找到了存在漏洞的 sql 语句:
  清单 3. 存在漏洞的 SQL 语句
  ResultSet resultSet = statement.executeQuery("SELECT COUNT(*)FROM PEOPLE WHERE USER_ID
  = '"+ user +"' AND PASSWORD='" + password + "'");
  /* BAD - user input should always be sanitized */
  虽然有时候对于经验丰富的开发者来说,对于逻辑简单程序能够直接定位到某个 java 文件,省去一些步骤,但是大部分情况下,我们都需要一步步的去分析。而对于 Glass Box 发现的漏洞,则可以大大节省开发人员定位代码漏洞的时间。Glass Box 可报告出漏洞的具体位置信息,如方法名、类名、文件名和行号等信息;并可报告运行时信息。如图 6 所示。
  图 6. Glass Box 问题信息
 
  总结
  黑盒测试技术由于无法获取应用程序的内部信息,导致扫描覆盖率偏低,且无法提供详细的调试信息;而白盒测试技术的代价过于高昂,需要大量的人工成本,且误报率较高。而 Glass Box 是有别于传统黑盒测试和白盒测试的一种混合测试技术,将有效解决这一难题,为客户创造更好的价值。

posted @ 2014-08-05 09:55 顺其自然EVO 阅读(646) | 评论 (0)编辑 收藏

利用LoadRunner编写socket性能测试脚本

 一、概述
  Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力。其中就有此次要讨论的socket套接字操作。
  二、socket概述
  socket是操作系统中I/O系统的网络延伸部分,它扩展了操作系统的基本I/O到网络通信,使进程和机器之间的通信成为可能。如果想完全地理解socket在Loadrunner中如何工作的,熟悉一些关于它的历史会很有帮助。
  当前常用的socket,最早起源于BSD UNIX类的操作系统。在UNIX系统上,比如BSD,把对网络的支持加入操作系统,以一种扩展现有文件描述符(后注)结构的方法来实现的。Socket 可以被看成一个标准的文件描述符。在 UNIX 类的平台上,其中包括open()、read()、write()和close()。很多时间,程序并不需要知道它正在把数据写进一个文件、终端、或是一个TCP连接。
  系统调用被加入并和socket一起工作,而很多现有的系统调用同样能和socket一起工作。因此,一个socket允许您使用标准的操作系统和其他的计算机,以及您自己机器上的不同进程来通信。
  然而,socket的确存在一些不同工作方式。最明显地就是建立socket的方法。很多文件是通过调用open()函数来打开的,但socket是通过调用socket()函数来建立的,并且还需要另外的调用来连接和激活他们。recv()和send()这两个系统调用和read()和write()极为相似。
  Socket是一套建立在TCP/IP协议上的接口不是一个协议,只要底层实现TCP IP协议,都可以用socket进行通信。
  应用层:  HTTP  FTP  SMTP  Web
  传输层:  在两个应用程序之间提供了逻辑而不是物理的通信基于流的TCP和基于数据包的UDP
  文件描述符一般是指一个文件或某个类似文件的实体。内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
  文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
  三、SOCKET连接过程
  根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
  服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
  客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
  连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
  四、开发原理
  服务器:使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。
  客户端:使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。
  Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。
  五、Loadrunner中socket相关函数浅析
  Loadrunner对于脚本函数有一份帮助文档。利用好此文档,其实对于性能测试所需脚本就已足以。
  当我们打开Create/Edit Scripts,并打开脚本录制页面时,摁下F1便可打开《HP LoadRunner Online Function Reference》。在这帮助文档中找到“键入关键字进行查找”输入框。利用它查找我们所需的socket函数了。
  几乎所有关于socket的函数,都是以lrs开头的。
基本操作函数:
lrs_startup 初始化 WinSock DLL
lrs_create_socket 初始化套接字
lrs_send 在数据报上(UDP)或者向流套接字(TCP)发送数据
lrs_receive 接收来自数据报或流套接字的数据
lrs_disable_socket 禁用套接字操作
lrs_close_socket 关闭打开的套接字
lrs_cleanup 终止 WinSock DLL 的使用,回收相关资源。VuGen 在 Windows 上使用 Windows 套接字协议支持应用程序的录制和回放;而在UNIX 平台上仅支持回放
lrs_accept_connection 接受侦听套接字连接
lrs_close_socket 关闭打开的套接字
lrs_create_socket 初始化套接字
lrs_disable_socket 禁用套接字操作
lrs_exclude_socket 重播期间排除套接字
lrs_get_socket_attrib 获取套接字属性
lrs_get_socket_handler 获取指定套接字的套接字处理程序
lrs_length_receive 接收来自指定长度的缓冲区的数据
lrs_receive 接收来自套接字的数据
lrs_receive_ex 接收来自数据报或流套接字的数据(具有特定长度)
lrs_send 将数据发送到数据报上或流套接字中
lrs_set_receive_option 设置套接字接收选项
lrs_set_socket_handler 设置特定套接字的套接字处理程序
lrs_set_socket_options 设置套接字选项
  缓冲区函数:
lrs_free_buffer 释放分配给缓冲区的内存
lrs_get_buffer_by_name 从数据文件中获取缓冲区及其大小
lrs_get_last_received_buffer 获取套接字上接收到的最后的缓冲区及其大小
lrs_get_last_received_buffer_size 获取套接字上接收到的最后一个缓冲区的大小
lrs_get_received_buffer 获取最后接收到的缓冲区或其一部分
lrs_get_static_buffer 获取静态缓冲区或其一部分
lrs_get_user_buffer 获取套接字的用户数据的内容
lrs_get_user_buffer_size 获取套接字的用户数据的大小
lrs_set_send_buffer 指定要在套接字上发送的缓冲区
  环境函数:
  lrs_cleanup 终止Windows套接字 DLL 的使用
  lrs_startup 初始化 Windows 套接字 DLL
  关联语句函数:
  lrs_save_param 将静态或接收到的缓冲区(或缓冲区部分)保存到参数中
  lrs_save_param_ex 将用户、静态或接收到的缓冲区(或缓冲区部分)保存到参数中
  lrs_save_searched_string 在静态或接收到的缓冲区中搜索出现的字符串,将出现字符串的缓冲区部分保存到参数中
  转换函数
  lrs_ascii_to_ebcdic 将缓冲区数据从 ASCII 格式转换成 EBCDIC 格式
  lrs_decimal_to_hex_string 将十进制整数转换为十六进制字符串
  lrs_ebcdic_to_ascii 将缓冲区数据从 EBCDIC 格式转换成ASCII 格式
  lrs_hex_string_to_int 将十六进制字符串转换为整数
  超时函数:(这一堆函数,是可以对同一个socket生效的)
  lrs_set_accept_timeout 为接受套接字设置超时
  lrs_set_connect_timeout 为连接到套接字设置超时
  lrs_set_recv_timeout 执行lrs_receive命令后,等待服务器返回消息的超时时间,即服务器的响应时间。
  lrs_set_recv_timeout2 创建连接成功,接收到服务器返回的消息后,获取匹配消息的超时时间。lrs_receive接收到数据后,会和预期的数据长度进行比较,如果长度不匹配,它将重新从套接字上读取数据,直到超时为止。
  lrs_set_send_timeout 为发送套接字数据设置超时
  六、实战讲解
  在此只做简单的知识普及,便于快速上手编写socket测试脚本。简述创建连接,收发协议,关闭连接的过程。
  初始化
//存放通信返回报文
char * ActualBuffer="";
//存放返回报文长度,切记附初值
int numberOfResponse = -1;
//链接是否创建成功,判断值
int rc = 0;
//返回报文是否成功,判断值
int msgOk=-1;
//存放返回报文
char * position="";
//返回报文是否成功标识
char * passMsg="succee";
 服务器监听
//--------------创建连接-----------------
rc= lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=<RemoteHost>", LrsLastArg);
if (rc==0){
//判断连接是否创建成功
lr_output_message("Socket was successfully created ");
}
else{
lr_output_message("An error occurred while creating the socket, Error Code: %d", rc);
}
//--------------创建连接-----------------
  收发协议
lrs_send("socket0", "buf0", LrsLastArg);
//往“socket0”发送"buf0"
lrs_set_receive_option(EndMarker, BinaryStringTerminator, "</html>");
//设置接收协议包选项,注"</html>"以实际定义协议为准,如果不设置次项。执行到lrs_receive的时候,log里面打印Waiting for writable socket 10
//secs, 0 usecs,都需要等待10秒钟。是这样的,因为你在data.ws中定义了recv buffer的长度,例如你定义为100,但是socket上的返回buffer长度不
//是100,这时候,loadrunner会尝试再次去读取,直到读到长度为100的buffer才算成功。
lrs_receive("socket0", "buf1","Flags=MSG_PEEK ", LrsLastArg);
//将“socket0”中返回的数据存放到“buf1”中
  参数配置
  可能细心的同学已经发现了,buf0与buf1是从哪里来的。其实这俩兄弟是在data.ws中被定义的,如下所示:
  ;WSRData 2 1
  send buf0 5120
  "<参数化>"
  recv buf1 1024
  -1
  5120:此数值为socket协议传输内容长度,切记严格输入正确长度值。
  "<参数化>":为buf0所传输内容。相对于loadrunner的http协议参数用{}来说,socket协议参数化采用<>作为定义符。
  接收参数判断
  在做了接收之后,我们需要提取“buf1”中的某些关键字符作为通信成功标识。
//获取套接字上接收到的最后的缓冲区及其大小
lrs_get_last_received_buffer("socket0",&ActualBuffer,&numberOfResponse);
//查询返回报文是否成功
position = (char *)strstr(ActualBuffer, passMsg);
// strstr has returned the address. Now calculate * the offset from the beginning of str
msgOk = (int)(position - ActualBuffer + 1);
if(msgOk>0){
lr_end_transaction("核心对私维护", LR_PASS);
lr_output_message("本次交易:%s",ActualBuffer);
}
else{
lr_end_transaction("核心对私维护", LR_FAIL);
lr_error_message("本次交易:%s",ActualBuffer);
}
关闭连接
//--------------断开socket--------------
lrs_disable_socket("socket0", DISABLE_SEND_RECV);
//--------------关闭socket--------------
lrs_close_socket("socket0");
  六、总结
  简要描述了利用Loadrunner编写socket性能测试脚本的过程,如有错漏,请予以指正。

posted @ 2014-08-05 09:53 顺其自然EVO 阅读(17352) | 评论 (0)编辑 收藏

简单明了的TestLink配置手册

     摘要: 安装完TestLink的下一步就是配置了,Testlink的配置信息包含很多方面,从日志信息、与其它bug管理工具的连接、自定义产生的文档、Email信息配置、用户认证配置、GUI定制、测试执行设置、测试规约、附件、需求支持、混合功能配置等等,在此一并列出。希望对你的TestLink的配置有所帮助,在此也声明一点,TestLink系统配置是很庞大的,部分信息是从网上搜集的。  1、配置文件概览  ...  阅读全文

posted @ 2014-08-05 09:50 顺其自然EVO 阅读(2457) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 71 72 73 74 75 76 77 78 79 下一页 Last 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜