本文主要讲述了 Socket 协议脚本的基础知识和编写方法, 让大家能够在短时间内快速掌握简单的 Socket 协议脚本的编写方法.
1.socket 协议介绍
Socket 协议有万能协议之称, 很多系统底层都是用的 socket 协议, 用处十分广泛.
1.1 Socket 通讯方式说明
与 socket 通讯有两种方式, 一种是建立长连接, 建立后不停的发送, 接收; 另一种是建立短连接, 即建立连接发送报文, 接收报文关闭连接
1.2 Socket 协议发送的 buf 类型介绍
Send buffer 类型分为字符串和 xml 类型
1.3 Socket 协议脚本编写前提:
与项目组沟通, 确认是否是 socket 协议, 由项目组提供服务器 IP 和端口号还有 socket 协议交易的报文发送及接收报文对, 及交易接口文档, 了解清楚报文的数据长度, 参数化字段, 结构, 代表什么等, 了解清楚后进行 socket 协议脚本的开发.
1.4,Socket 协议脚本函数说明及实例:
1) 名称 lrs_create_socket();
创建 socket 连接, 添加 IP 和端口号, 如果创建成功返回值为 0, 反之则返回为非 0 数值.(对于长连接, 建立 socket 连接放在 vuser_init 函数中, 短连接放在 Action 中即可) 实例: lrs_create_socket("socket0","TCP","RemoteHost=180.170.150.230:7700", LrsLastArg);
2) 名称 lrs_send();
发送 socket 请求消息, 取缓冲区 buf0 的报文并发送.
实例: lrs_send("socket0","buf1",LrsLastArg);
3) 名称 lrs_receive();
接收 socket 的响应报文, 放置 buf1 中.
实例: lrs_receive("socket0","buf2",LrsLastArg);
4) 名称 lrs_get_last_received_buffer();
获取最后收到的 buffer 和大小, 其中将最后收到的 buffer 的值赋给 RecvBuf 变量, 将大小赋值给 RecvLen.
实例: lrs_get_last_received_buffer("socket0",&recvBuf,&recvLen);
5) 名称 lrs_free_buffer();
为防止内存泄露, 释放内存空间.
实例: lrs_free_buffer(recvBuf);
6) 名称 lrs_close_socket();
关闭 Socket 连接,(对于长连接, 关闭 socket 连接应放在 vuser_end 函数中)
实例: lrs_close_socket("socket0");
其他常用的 Socket 函数:
- lrs_set_send_buffer("socket0", sSendPkg, iLenOfPkg );// 指定要发送的 socket 信息
- lrs_get_buffer_by_name("buf0", sSendPkg, iLenOfPkg);// 获取收到的 buffer 和大小
- lrs_length_send("socket0","buf0",1,"Size=4","Encoding=1",LrsLastArg);
关联函数:
- lrs_save_param_ex("socket0","received","",151,7,"ascii","response");// 取指定位置字符串保存到变量, 以便判断事务是否成功
- lrs_save_searched_string();// 在指定位置搜索字符串, 将出现的字符串报错到参数中
超时函数
- lrs_set_connect_timeout();// 设置连接超时时间
- lrs_set_recv_timeout();// 设置服务器响应超时时间
- lrs_set_recv_timeout2();// 设置接收超时时间, 使系统不去检查回收的内容是否一致
2,Socket 脚本编写
2.1 简单划分步骤
这种方法是我无意在一片文章中看到的, 总体说来, 比较简单. 就像把大象放进冰箱一样, 总共分三步:
第一步: 把冰箱门打开
- // 建立到服务端的连接
- rc = lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=128.64.64.23:8988", 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_receive("socket0", "buf1", LrsLastArg);// 将 "socke0" 中返回的数据存放到 "buf1" 中
第三步: 把冰箱门带上
- // 关闭连接
- lrs_close_socket("socket0");
2.2 详细划分步骤
◇变量的声明与定义
◇ 创建 socket 连接
◇ 发送 socket 请求
◇ 接收 socket 响应
◇ 从返回 Buffer 中抽取结果
◇ 结果判断
◇ 释放内存
◇ 断开连接.
2.3 实例脚本
下面我们就是用一个实际项目不同报文格式的脚本进行讲解;
若项目是短连接, 且报文不是从文件中读取信息时, vuser_init 和 vuser_end 部分默认即可, 主要在 Action 中开发测试脚本和在 data.ws 中传输数据到 Action 的代码中.
Vuser_init.c
#include "lrs.h" vuser_init() { lrs_startup(257); return 0; } |
Action.c
#include "lrs.h" Action() { int rc,rv;// 保存连接成功返回值 char *recvBuf;// 保存接收数据的内容 int recvLen;// 保存接收数据的大小 /* 对于长连接,建立 socket 连接放在 vuser_init 函数中,短连接放在 Action 中即可 */ rc=lrs_create_socket("socket0","TCP","RemoteHost=IP: 端口", LrsLastArg); // 判断连接是否创建成功 if(rc==0){ lr_output_message("Socket 连接创建成功"); } else{ lr_error_message("Socket 连接创建失败!错误码 =%d",rc); return -1; } lr_start_transaction("XXXX_1234_FCX");// 事务开始 // 发送 socket 请求消息(数据包内容放在 data.ws 中) lrs_send("socket0", "buf0", LrsLastArg); // 取缓冲区 buf0 的报文并发送 rv = lrs_receive("socket0", "buf1", LrsLastArg);// 接收响应报文 if(rv==0){ lr_output_message("Socket 接收返回消息成功"); } else{ lr_error_message("Socket 接收返回消息失败!错误码 =%d",rv); return -1; } // 获取最后收到的 buffer 和大小 lrs_get_last_received_buffer("socket0",&recvBuf,&recvLen); /* 设置检查点,验证返回数据是否成功,这个根据各交易具体情况进行判断,以下示例是通过返回报文的长度大于 3 即为成功 */ if(recvLen>3){ lr_end_transaction("XXXX_1234_FCX",PASS); } else{ lr_end_transaction("XXXX_1234_FCX",FAIL); lr_error_message("XXXX_8550_FCX Fail! 出错信息:[%s]", recvBuf);// 交易失败时,输出 RecvBuf 返回信息,用于排查出错原因 } lrs_free_buffer(recvBuf); // 释放 recvBuf 内存空间,否则会引起内存泄露 /* 关闭 Socket 连接, 对于长连接,关闭 socket 连接应放在 vuser_end 函数中 */ lrs_close_socket("socket0"); return 0; } |
data.ws
1)xml 报文格式
;WSRData 2 1 send buf0 360 "<?xmlversion=\"1.0\"encoding=\"GBK\"?>" "<TRANINFO>" "<HEAD>" "<TransCode>S001</TransCode>" "<TransDate>20170613</TransDate>" "<TransTime>144206</TransTime>" "<TransNo>21219603</TransNo>" "<Operator>999088</Operator>" "<TransInst>70090</TransInst>" "</HEAD>" "<MSG>" "<CustomerID><userID></CustomerID>"// 客户编号 "<Type>3</Type>"// 查询类型 "<BusinessType>01</BusinessType>"// 业务类型 "</MSG>" "</TRANINFO>" recv buf1 300 -1 |
2)16 进制报文格式
;WSRData 2 1 send buf0 32 "\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" " " "\x00\x00\x00\x00" "PID<tran>" recv buf1 197 "\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x1e\x00\x00\x00\x00" "STW -1" "\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x1e\x00\x00\x00\x00" "STT" "\x1f" -1 |
其中 buf0 代表发送的报文的名称, 后跟的数字代码发送报文长度, 其下放置发送报文; buf1 代表接收报文的名称, 后跟数字代表接收报文长度, 其下放置接收报文.
注意: 该协议脚本参数化格式为:< 参数名 >
来源: https://www.cnblogs.com/zwh-Seeking/p/10838672.html