之前在网上找到 socket 函数的说明,但是这两个函数并没有详细介绍,所以根据官方文档整理了一下
接收来自指定长度的缓冲区的数据,主要步骤是先确定长度数据位置,获取到长度数据,然后根据长度数据去获取实际数据。
int lrs_length_receive(char **socket_descriptor*, char **buffer*, int *location_option*,
[char* *locators*], [char* *additional_params*],LrsLastArg );
location_option (定位模式),使用哪种方法进行定位:
lrs_receive
功能一样)locator(定位器,跟上一个参数对应),对应上面的参数,对应的 locator 参数有三种组合如下:
Offset=xxx
(默认 0),长度,Size=xxx
LB=xxx
RB=xxx
Ordinal=
,偏移量,Offset=xxx
Size=xxx
LB=xxx
Ordinal=
偏移量:Offset=xxx
additional_params(额外参数),主要包括缓冲区长度格式和长度计算相关的其它问题:
Encoding=
,编码:0,十六进制(默认),1,十进制Order=
,顺序,0,根据客户端(默认),1,根据网络顺序SubtractSize=
,是否减去长度,0,不减去本身长度(默认),1,减去本身长度Flags=
,用法不明LrsLastArg,参数结尾标识
成功返回 0,否则返回错误码。
例子 1:
下面的例子用location_option=1
的方式来说明,buffer1
包含2
字节的长度数据(粗体)和实际的数据
首先得到长度数据51
之后,lrs_length_receive
继续从socket0
读取51
字节的数据到buffer2
,注意这里不需要设置 offset,使用默认值即可。
buffer1
51aaabbccdddeeeeeeeeeeeeeeffffffffffffgggggghhhhhhhi
lrs_create_socket("socket0","TCP", "RemoteHost=bona.mercury.com:7", LrsLastArg);
lrs_send("socket0","buffer1", LrsLastArg);
lrs_length_receive("socket0","buffer2", OffsetSize, "Size=2", LrsLastArg);
这个例子:
2
读取前两位长度数据,也就是51
,51
之后,51
字节的数据。例子 2:
这个例子使用location_option=2
的定位方式,左边界LLLL
,右边界RRRR
,序数设置为2
(表示以第二个LLLL
作为左边界),偏移量设置为27
(表示从黑体开始往右偏移27
字节),根据右边界RRRR
可以判定长度数据为9
(黑体),然后函数继续读取右边界后面开始的 9 个字节的数据,在这里为Requested
,将数据存入buff4
,lrs_receive
将剩下的数据存入buffer
。
buffer3
12LLLL34*LLLLOOOOOfffffsssssseeeeeTTTTTT9*RRRRRequestedZZZZZZZZZZZZZZZZZZZZ2LLLLAAAAAAAAAAAAAAAAAAAAAAEndBuf
lrs_create_socket("socket0","TCP", "RemoteHost=bona.mercury.com:7", LrsLastArg);
lrs_send("socket0","buffer3", LrsLastArg);
lrs_length_receive("socket0","buffer4", 2, "LB=LLLL", "RB=RRRR","Offset=27", "Ordinal=2", LrsLastArg);
// 获取剩余数据
lrs_receive("socket0","buffer5", LrsLastArg);
这个例子:
LLLL
作为左边界,然后偏移量为 27,也就是到了字符串中的TTTTT
后面RRRR
,所以可以得到表示长度的数据为黑体的9
RRRR
之后获取9
个字符即为期望的字符,在本例中为Requested
例子 3:
这个例子使用location_option=2
的定位方式,设置左边界\\x00\\x00\\x00\\x07
,然后根据偏移量设置Offset=7
往后便宜7
个字节,根据长度设置size=2
取出 2 字节的长度数据16
,由于设置了SubtractSize=1
,所以需要减去本身的长度2
(所以实际要获取的长度为16-2=14
),所以获取数字16
以后的14
的字节,在这个例子中为RequestedData
,最后用lrs_receive
获取剩下的数据。
buffer6
12LLLL34*\x00\x00\x00\x07eTTTTTT16*RequestedDataZZZZZZZZZZZZZZZZZZZZ2LLLLAAAAAAAAAAAAAAAAAEndBuf
lrs_create_socket("socket0","TCP", "RemoteHost=bona.mercury.com:7",
lrs_send("socket0","buffer6", LrsLastArg);
lrs_length_receive("socket0","buffer7", 3, "LB/BIN=\\x00\\x00\\x00\\x07","size=2", "Offset=7", "SubtractSize=0",LrsLastArg);
这个例子:
\\x00\\x00\\x00\\x07
,根据偏移量7
往右偏移到了TTTTTT
Size=2
,所以可以获取到之后的两个字节16
,这个表示的我们希望的长度数据SubtractSize=0
说明长度16
还包含了本身的长度2
,所以减去之后,我们感兴趣的长度只有14
了。16
后的14
个字符即可,本例中为RequestedData
。函数读取指定长度的数据到buffer
,长度数据在数据本身里面,用户必须清楚的知道长度数据的具体位置,并使用location_option
和locators
两个参数来指定长度数据的具体位置,lrs_length_receive
首先得到长度数据,然后根据长度数据读取相应的数据到buffer
。
location_option
参数说明
lrs_length_receive
这时候功能跟lrs_receive
一样。但是lrs_set_receive_option
设置的选项不影响lrs_length_receive
(会影响到lrs_receive
)。 LB
和RB
,读取的数据为紧接着右边界后面的数据(长度为左右边界之间的数据决定),同时Offset
和Ordinal
可以作为可选参数。LB/BIN
和RB/BIN
来表示左边界和右边界,如RB/BIN=\\x00\\x00\\x01\\x00\\x00\\x00
Size
决定,同时Offset
和Ordinal
可以作为可选参数。locator 参数: Locator联合起来定位长度数据的位置,如:"LB=LeftLeft ", "Size=1","Offset=18"
location_option=1
(OffsetSize
)中使用Offset
表示从开始到长度数据有多少字节。location_option=2
或3
(LeftRightBoundaries
或者LeftBoundarySize
)中Offset
表示长度数据在左边界+Offset
个字节后面,这在左边界之后不确定内容但是是固定字节数的时候很有用。例如,有一个固定的左边界ABC
,之后始终有两个未知的数据,就可以设置LB=ABC
和Offset=2
Ordinal 参数
location_option=2
或3
(LeftRightBoundaries
或LeftBoundarySize
),它表示长度数据在第几个左边界的后面。例如左边界 ABC 出现了很多次,如果设置 Ordinal=2,则表示长度数据在第二个 ABC 之后。Offset
一起使用,先确定了第几个左边界,然后在左边界后面偏移Offset
个字节的数据来确定长度。 额外的参数
Order=1
,Encoding=1
SubtractSize
可以让你从长度数据中减去本身的长度,如长度数据是16
,实际计算的时候减去本身长度2
,即为14
。向流套接字发送指定长度的缓冲区数据
int lrs_length_send(char **socket_descriptor*, char **buffer*, int *location_option*,
[char* *locators*], [char* *additional_params*],LrsLastArg );
lrs_send
功能一样)locator(定位器,跟上一个参数对应)对应上面的参数,对应的 locator 参数如下:
Offset=xxx"
(默认 0) Size=xxx
LB=xxx
RB=xxx
Ordinal=
,偏移量,Offset=xxx
Size=xxx
LB=xxx
Ordinal=
,偏移量:Offset=xxx
additional_params(额外参数)缓冲区长度格式和长度计算其它问题:
Encoding=
,编码,0,十六进制(默认),1,十进制Order=
,顺序,0,根据客户端(默认),1,根据网络顺序SubtractSize=
,是否减去长度,0,不减去本身长度(默认),1,减去本身长度Flags=
,用法不明 LrsLastArg
参数结尾标识成功返回 0,否则返回错误码。
在这个例子中,buf6
通过socket0
发送,数据使用了参数化,NameParameter
是一个参数,从一系列的数据中取值。 4
是长度数据,但是,随着参数NameParameter
变化,长度也在随着变化,比如:David
长度应该改为5
,Michael
长度应该改为7
。
buf6
Start Data LBoundary & Offset:4:RBoundary
#include "lrs.h"
Action() {
lrs_create_socket("socket0","TCP","RemoteHost=bonaparte.mercury.co.il:7",LrsLastArg);
lrs_length_send("socket0","buf6",LeftRightBoundaries,"LB=LBoundary","RB=:RBoundary", "Offset=10",LrsLastArg);
lrs_close_socket("socket0");
return 0;
}
通过lrs_length_send
可以实现下面的动态发送数据。
===SENT BUFFER (on first iteration) ===
"Start Data LBoundary & Offset:5:RBoundaryDavid"
===SENT BUFFER (on second iteration) ===
"Start Data LBoundary & Offset:7:RBoundaryMichael"
在这个例子中
LBoundary
,然后偏移量为10
,定位到了Offset:
后面的位置:RBoundary
,所以中间的部分就是长度数据这个函数大部分参数跟lrs_length_receive
相同。
lrs_length_send
可以用来发送指定长度的数据,这在发送数据中包含参数化数据的时候很有用,因为每次发送的数据长度不一致,通过函数可以在每次发送数据之前将正确的长度写入到发送数据中去。
长度数据的查找方法跟lrs_length_receive
类似,也是通过locator
和location_option
两个参数来定位。
在调用函数之前,用户必须明确知道长度数据在哪里,函数首先计算长度,然后写入长度规定的字节数到缓冲区发送出去。
socket_descriptor,buffer
这两个参数跟lrs_send
完全一致。
location_option(定位模式)
lrs_length_send
跟lrs_send
完全一致。 Offset
规定了从数据开始的偏移量,Size
规定了长度数据所占的字节数,Offset
和Size
参数就可以确定长度数据的具体位置。如Offset=6
, Size=4
。需要计算长度的数据为长度数据之后的数据。Offset
的默认值是 0(从数据最开始算起)LB
和RB
,需要计算长度的数据为右边界后面的数据。Offset
和Ordinal
用法同上,不再介绍。/BIN
,如RB/BIN=\\x00\\x00\\x01\\x00\\x00\\x00
Size
个字节,参数为LB
,Size
,同时Offset
和Ordinal
也可以作为可选参数,用法同上。 Locator 参数
关于 Offset 参数的用法,Ordinal 的用法,以及附加参数的用法同函数 lrs_length_receive