转载地址:http://blog.csdn.net/diy8187/archive/2009/03/27/4028358.aspx 一、什么是Winsock? Winsock 是Windows Sockets的简写,是用于TCP/IP与Windows之间的通信的接口。TCP/IP被称为“Internet语言”,基本上说,Internet就是由那些通过TCP/IP进行通信的系统组成的。目前,大部分基于Windows操作系统或者IBM OS/2操作系统的流行Internet应用程序是按照WinSock标准来开发的。 WinSock是一个.dll(动态链接库)并且在Windows下运行。WINSOCK.DLL是连接TCP/IP的接口,然后通过TCP/IP,连接到Internet。 下图以最简明的方式表明了WinSock是如何工作的: WINSOCK.DLL实际上担当WinSock应用程序和TCP/IP堆栈的中间层。WinSock应用程序告诉WINSOCK.DLL要做什么,然后WINSOCK.DLL翻译这些命令给TCP/IP堆栈,然后TCP/IP堆栈传递这些命令给Internet。二、LoadRunner和Winsock 在我们投入到分析LR Winsock 解决方案的需求前,让我们先离题一点点,来讨论不同的协议是如何工作的。从上文的介绍,你可以知道,有许多的高级协议,例如FTP,HTTP等等。所有Windows基础应用程序(例如IE,WS-FTP)使用Winsock作为与网络通信的接口。因此,任何高级协议将通过Winsock连接到网络。 什么时候在LR中使用WinSock呢?到如今,你肯定非常熟悉LR是如何工作的。LR本质上是在录制期间捕获API调用然后将他们回放。因此当你创建了一个LR的Web脚本,Vugen将捕获所有在浏览器上操作而产生的HTTP调用。LR支持许多其它的协议,例如Oracle OCI,ODBC,Sybase,和SAP等等。在所有的这些协议中,LR通过勾住(hooks into)API,就能够捕获API调用产生的响应。现在,假设某个协议是LR不支持的。既然大多数网络协议使用Winsock作为接口,如果我们在Winsock层上录制脚本,我们就可以捕获几乎所有在Windows上的应用程序。因此,当LR支持的其他协议不能工作的时候,我们就可以使用Winsock了。三、使用Winsock录制脚本 在LR中创建一个新的Vuser脚本,并且在Vuser type中选择Winsock。如下图 在web Vuser脚本中,指定将要进行录制脚本的URL后,Vugen就会启动浏览器并开始录制。但在Winsock类型的脚本中,你可以对任何应用程序进行录制,而不仅仅是浏览器。因此你需要指定要录制的应用程序,如下图所示: 这个例子中,我们为一个web应用程序创建了一个Winsock脚本,因此我们将通过给出IEXPLORE.EXE的路径来调用浏览器。这可能没有多大意义,因为LR已经支持使用HTTP协议进行录制,但我选择web应用程序,仅仅是为了简单的举例说明。四、Winsock脚本 一个典型的Winsock脚本可能就像下图所示: 这是通过录制www.yahoo.com得到的一个脚本。你可以看出,Winsock录制的内容主要由:打开一个socket连接、发送buffer和接收buffer组成。如果你看脚本,你将会发现Winsock脚本由4个部分组成,而不像web脚本中通常有3个部分。如下图: 第四个部分是data.ws,它包含了在Actions中的lrs_send和lrs_receive语句所涉及到的buffer。下图展示了在data.ws中的buffer的一个例子。 buf2包含了向www.yahoo.com发出的请求,buf5包含了从服务器接收到的响应。你可以看出,Winsock脚本并不像web脚本那样“漂亮”!所以我们把它作为最后录制手段。在一个接收buffer中,bufxx后面跟着一个数字,这个数字表示接收的总字节数量。例如,在buf5中,接收了2048个字节。 注意:你会看到有一些buffer只包含一个“!”,它仅仅只是一个网络确认。它不会对应用程序有任何作用。可以把它们注释掉。不能在data.ws中注释,你可以在Actions部分中把相应的lrs_send和lrs_receive buffer注释掉。因此在这个例子中,buffer0,1,3和4可以在action部分中注释掉,如下: 这样将会提高脚本的运行速度。五、创建Winsock脚本 以下是创建winsock脚本的六个步骤。 1、使用VuGen录制基本脚本。 2、增强脚本。 3、定义参数(可选的)。 4、关联语句(可选的)。 5、设定运行时属性设置。 6、在VuGen中运行脚本。 1、使用VuGen录制基本脚本。 和前面所描述的方法一样,调用Vugen并创建一个新的Vuser脚本。这将是你最基础的脚本。你可以注释掉包含“!”的buffer。 练习1 作为一个练习,创建一个简单的Winsock脚本,录制动作:使用jojo/bean登录到MercuryWebTours站点然后登出。保存脚本,命名为Winsock_1。创建一个类似的web脚本,使用HTTP协议。保存脚本,命名为WebWinsock_1。不要替换动态的session ID。让脚本停留在刚录制完毕的状态。比较这两个,想想Winsock脚本和web脚本相比较有什么相象之处。 当你成功登录后,你会得到一个提示消息“Welcome,jojo,......”。既然所有发送和接收buffer都记录在data.ws文件中,你可以在你的data.ws中定位字符串“Welcome,jojo”。 1.1)你所找到的包含“Welcome,jojo”的buffer的号码是多少?你能解释为什么这个buffer是个接收buffer而不是个发送buffer?这个字符串是不是仅仅就是“Welcome,jojo”,还是带有HTML标签?(答:buffer号码常常不会保持为一个常量:它们可能在不同的录制时会有所改变。当你登陆,基于旧的ID,会从服务器那里接收到一个欢迎信息。因此字符串“Welcome,jojo”会出现在一个接收buffer中。并且该字符串将会带有HTML标签。如果你只需要字符串的一部分,你将不得不提有计划地提取它。) 仔细观察脚本。在data.ws文件中查找MSO=SIDxxxxxxxxx,xxxxxxxxx表示9个数字。这是自从1970年1月1号到现在的秒数。MercuryWebTours站点基于当前时间工作,cookie和session ID都是以时间为基础。因此你脚本中的timestamp(xxxxxxxxx)对应了你录制时的时间。当运行脚本时,你必须改变它以获取当前时间,然后转换当前时间为字符串,并且作为一个参数。C中的函数time()返回一个整数,该整数是自从1970年1月1号以来的总秒数。在脚本的开头获取时间,转换这个整数为LR的一个参数,用这个参数替换data.ws中所有这个数字出现的地方。这样,脚本将被设置成使用当前时间。 1.2)修改时间完毕后,运行上面的脚本。在执行日志中查找字符"incorrectly"。你将会找到"You've reached this page incorrectly"。运行脚本WebWinsock_1。你将会在运行视图看到类似的信息。为什么会出现整个问题?(答:因为session ID没有被关联。我们正在使用已经无效的老session ID。) 注意:文件data.ws中的接收buffer在每次回放后不会被更新。data.ws文件在录制时创建,回放时保持不变。因此,一旦脚本被录制完毕后或者工作的时候,接收buffer的内容不会被影响。LR使用发送buffer中的数据向网络发送请求,然后对从服务器接收到的响应和接收buffer中的期望响应进行比较。也注意下,只比较大小,不是实际内容。如果文件data.ws接收buffer中存在"rob",然后服务器响应"bob",LR将认为通过了。但如果服务器响应"robert",LR将会提示产生了一个期望字节数不匹配的错误。 沿着相同的方面,让我们假定LR期望接收500字节。假定第一个10秒接收第一个100字节时,将产生超时并且停止运行。如果你希望LR等待更长的一段时间,你必须使用函数lrs_set_recv_timeout去修改默认的超时时间。 考虑相反的情况,你不希望在一个特定的buffer中接收所有的数据,而是只希望接收第一个100字节。这样你可以使用函数ltr_receive_ex,它可以指定你希望接收的字节数量。 2.增强脚本 通过插入事务,集合点和流程控制到脚本中,来增强脚本。不像web脚本那么易于阅读,在Winsock脚本中,步骤之间的区分不是很明显。因此在录制时,增加注释,事务和集合点(需要时)到脚本中就显得很重要。 如果脚本中需要任何逻辑,增加该逻辑(这是在普通脚本中的一种语句,对上面的脚本Winsock_1并不适用)。 3.定义参数(可选的) 为脚本中的已录制的固定值定义参数。通过参数取代固定值,你可以重复业务操作多次而使用不同的值。例如,在上面的脚本中,你可以使用不同的userIDs/passwords取代jojo/bean。 4.关联语句(可选的) 关联语句使你能够在接下来的业务处理中使用前面的业务处理产生的结果。现在你知道,在前面章节中你所录制的web脚本中,服务器产生的session ID将不得不被关联来使得脚本得以正常工作。这也同样应用于Winsock脚本中。因此,你将不得不捕获并关联session ID。 我们将不在这里做关于捕获和关联session ID的练习,因为类似这样的练习是证明你自己的一部分。但我们将在这一节中,讨论关联的总体概貌。 例如,假定你将要在下面的接收buffer中捕获PID(这是LR函数参考的一个例子): 在典型的web脚本中,你将使用web_create_html_param并且用“PID”和“q2”为边界来捕获数据。 在winsock脚本中,你将使用lrs_save_param,它保存静态或接收buffer中的数据作为参数。参看下面的示例: 和web_create_html_param不同,lrs_save_param出现在发出请求的后面。在这个例子中,第一个语句接收buf47。下面是那些在lrs_save_param语句中使用到的参数: socket2:在socket2上从一个buffer中捕获。 NULL:NULL指示参数必须从上个接收buffer中捕获。这个例子是buf47。如果你要从其它的buffer中捕获,你将必须指定buffer号码。 param1:LR参数名称,它将保存捕获的数据。 67:便宜量-在下面介绍。 5:将要捕获的长度。 偏移量:这是从buffer起始到开始捕获处所要跳过的字节数量。在上面得例子中,PID在buf47中,距离起始67个字节的地方开始。如何确定这个呢? 在data.ws中,高显示包含了要捕获的参数的整个buffer,然后按下F7。这样将会调出一个窗体,如下所示: 左边的一列中,你将看到每行相应的偏移量。在中间的4列,你将看到buffer的EBCDIC(扩充的二进制编码的十进制交换码)转化。在右边的一列,是实际的buffer本身。因此,如果你看实际buffer的第五行,那就是PID所在的行。但我们希望在该行的第三个位置后才开始捕获。该一行所对应的偏移量是64,然后在该行中,PID的偏移量是3,因此,总的偏移量就是67。 注意:在winsock中,没有类似web_find的语句,你将不得不捕获你正在查找的文本并且计划性地验证你是不是得到正确的文本。 5.配置运行时设置 运行时设置控制脚本执行时虚拟用户的行为。这些设置包括循环,日志和定时信息。 6.在Vugen中运行脚本 保存脚本,并且在Vugen中运行脚本以验证它是否正确地运行。