Windows sockets是Windows下的網絡程式設計接口,是一個與網絡協定無關的程式設計接口,幾乎所有的網絡協定都是它的一個子集。當沒有合适的協定來支援目前系統時,Windows sockets作為一種“萬能藥”,提供了一種基于低層的錄制方法。在Windows sockets協定下,任何用戶端與伺服器之間的互動隻是一種發送資料包和接收資料包的過程。
Vuser_init
#include "lrs.h"
vuser_init()
{
lrs_startup(257); //Windows Sockets初始化
//設定Socekt通訊參數
lrs_set_connect_timeout(10,0); //設定連接配接逾時時間
lrs_set_recv_timeout(20,0); //設定伺服器響應逾時時間
lrs_set_recv_timeout2 (10,0); //設定接收逾時時間
return 0;
}
Action
#include "LRPublic_HXB.h" //引用定制開發的LR公用函數庫
#include "lrs.h"
char TransName[] ="TransName1"; //事務名稱(如果有多個事務可定義多個變量,如TransName1、TransName2)
int RespCodeOff = 437; //響應封包表示交易處理是否成功的響應碼的偏移量
char RespCodeSuccess[] = "000000"; //響應封包中表示交易處理正确的響應碼内容
char *ActualBuffer; //儲存接收資料的内容
int NumberOfBytes; //儲存接收資料的大小
int rc; //儲存連接配接成功傳回值
Action()
{
//建立Socket連接配接(對長連接配接,建立Socket連接配接放在vuser_init函數中)
rc = lrs_create_socket ("socket0","TCP","RemoteHost=<P_HostIP>:<P_Port>",LrsLastArg);
if (rc != 0) //建立Socket連接配接失敗時記錄錯誤日志并退出本次疊代
{
lr_error_message("Socekt Connecting Failed”);
return 0;
}
lr_start_transaction(TransName);
//發送請求封包,這裡将buf0的内容發送到socket0這個已經聲明好的端口中
lrs_send("socket0", "buf0", LrsLastArg); //取緩沖區buf0的封包(已完成參數化資料替換)并發送
lrs_disable_socket("socket0",DISABLE_SEND); //發送完成後禁用socket的發送連接配接
//該函數将伺服器傳回的内容儲存在buf1中
lrs_receive("socket0", "buf1", LrsLastArg); //對短連接配接,接收響應封包(異步通訊模式不在此執行receive函數,需要在其他地方接收響應封包)
// lrs_length_receive("socket0", "buf1", OffsetSize, "Size=4", LrsLastArg); //對長連接配接,擷取傳回指定長度的響應封包(封包前4個位元組表示封包長度,如8583封包)
lrs_get_last_received_buffer ("socket0", &ActualBuffer, &NumberOfBytes); //擷取socket0最後收到的buffer和大小
//檢查點設定:根據傳回響應封包長度及響應碼進行判斷
if ( NumberOfBytes > 4)
{
//通過響應封包響應碼判斷事務執行狀态(若為查詢交易,可再細分查詢結果為空的情況,此種情況交易應為成功,但應記錄查詢結果為空的資訊)
if (strncmp(ActualBuffer + RespCodeOff, RespCodeSuccess, sizeof(RespCodeSuccess)-1) == 0){
lr_end_transaction(TransName,LR_PASS);
}else{
lr_end_transaction(TransName,LR_FAIL);
}
}else { //響應封包為空 或 僅收到"0000"心跳信号
lr_end_transaction(TransName,LR_FAIL);
lr_error_message("出錯(傳回封包為空或僅收到心跳信号)!");
}
lrs_free_buffer(ActualBuffer); //釋放ActualBuffer記憶體空間,否則會引起記憶體洩露
lrs_close_socket("socket0"); //關閉Socket(對長連接配接,關閉Socket連接配接應放在vuser_end函數中)
return 0;
}
Vuser_end
#include "lrs.h"
vuser_end()
{
lrs_cleanup(); //Windows Sockets退出清理
return 0;
}
Windows sockets協定會産生一個data.ws檔案,儲存所用的傳輸資料,一般要參數化send中的相關内容
data.ws檔案中的recv buf是我們回放腳本時從“Replay Log”中提取的,如果定義的recv buf數和實際響應封包的長度不一緻,會發生socket逾時,響應時間不準确導緻TPS上不去。
完成此協定腳本準備工作
1)IP和PORT
2)請求封包和響應封包規範
3)在響應封包中确定交易的成功碼存放的位置
相關函數
Lrs_receive_ex(“socket0”,”buf1”,”NumberOfBytesToRecv=60”,LrsLastArg);
在接受資料包時經常會出現服務端傳回的封包長度不定長的問題,如果接收封包長度不相等,LR會等10秒後再接收一次,這樣會導緻事務莫名奇妙地等待。因為可以根據經驗強制批定接收封包長度,避免逾時重讀的問題。
Lrs_save_param(“socket0”,LRS_LAST_RECEIVED,”result”,10,20);
//lrs_save_param(端口連接配接名,LRS_LAST_RECEIVED,參數名,偏移量,儲存長度);
該函數可以獲得伺服器傳回的内容并儲存到一個參數中
Lrs_save_param_ex(“socket0”,”user”,ActualBuffer,302,2,”ascii”,”successcode”);
”user”是将資料儲存到參數中的緩沖區類型,”user”為使用者緩沖區,”static”為data.ws中的靜态緩沖區,”received”為最後接收的緩沖區資料
Lrs_save_searched_string(“socket0”,LRS_LAST_RECEIVED,”result”,”LB=<title>”,”RB=</title>”,1,0,-1);
//Lrs_save_searched_string(端口連接配接名,LRS_LAST_RECEIVED,參數名,LB=左邊界,RB=右邊界,取值序号,偏移量,儲存長度);
當需要的資料不是固定的位置和長度時,那麼就需要通過左右邊界的方式來捕獲傳回值。
Mismatch的比對機制
Mismatch有兩種比對方式:長度比對和内容比對。長度比對就是當lrs_receive()接收到資料之後就會和我們期望的緩沖區資料進行長度對比,如果實際接收到的資料長度不等于我們期望值,就會報Mismatch錯誤。
如果我們用lrs_set_receive_option(Mismatch,MISMATCH_CONTENT)來指定比對方式為内容比對,那麼當lrs_receive()接收到資料之後就會和期望的資料内容進行比對對比,這時即使長度相同,内容不同也會報Mismatch錯誤。
回放時出現Mismatch錯誤不一定意味着回放失敗,因為有些傳回資料可能含有随機性。
Lrs_set_recv_timeout()與lrs_set_recv_timeout2()
lrs_set_recv_timeout()設定伺服器響應逾時時間,lrs_set_recv_timeout2 ()設定接收逾時時間。如果一個應用程式需要一個較長的時間處理請求,但是一旦處理完畢,伺服器就會用很快的速度傳回資料。可以用lrs_set_recv_timeout()來設定一個較大的逾時時間,而用lrs_set_recv_timeout2()設定一個較小的逾時時間來接收資料。而一些應用程式可能連接配接伺服器很快,但是可能由于網絡擁堵資料傳輸會花費比較長的時間,則設定相反。
相關概念
1 同步和異步
同步是發送和接收在同一個鍊路上;發送一個請求,等待傳回,然後再發送下一個請求;可以避免出現死鎖,一般共享某一資源的時候用。
異步是兩個鍊路上;發送一個請求,不等待傳回,随時可以再發下一個請求,可以提高效率,但必須保證是可以并發處理的;線程安全可使用異步
LR controller收集結果時不能差別同步和異步,Analysis的所有資訊都是loadrunner通過自己的計算方法得到的,響應時間即lr_start_transaction()到lr_end_transaction()的時間。
2 短連接配接和長連接配接
短連接配接的過程是:連接配接->傳輸資料->關閉連接配接,如Web網站http服務。短連接配接将lrs_create_socket()函數和lrs_close_socket()函數放在action中。
長連接配接的過程是:連接配接->傳輸資料->保持連接配接->傳輸資料->......->關閉連接配接,如資料庫連接配接。長連接配接将lrs_create_socket()函數放在init中,lrs_close_socket()函數放在end中。
3 同步長連接配接和異步長連接配接
Socket協定異步長連接配接性能測試腳本與同步長連接配接是相同的,隻是在統計處理能力和事務平均響應時間方面有差別:TCP同步長連接配接請求在并發時通過LoadRunner就可以統計TPS和響應時間,而TCP異步長連接配接方式伺服器處理交易請求在大并發壓力情況下并不是實時處理的,這就需要到被測系統中的資料庫中去統計。
4 單工、全雙工和半雙工
單工:裝置中發送器與接收器分工明确,隻能由發送器向接收器的單一固定方向上傳送資料
全雙工:裝置既是發送器也是接收器,可以同時在兩個方向上傳送資料
半雙工:同全雙工,但某一時刻隻能向同一方向傳送資料
5 異步雙工和異步單工
異步雙工:接收和發送在同一程式中,由兩個不同的子程序分别負責發送和接收
異步單工:接收和發送是用兩個不同的程式來完成