ReceiveAndParse (Socket function)
Receive bytes up to a given string (Socket class)
This method receives a string over a Janus Sockets connection.
It is designed for a string whose length
is not known beforehand but which is terminated by a known string or by
one of a known set of strings.
The ReceiveAndParse function has an effect similar to $Sock_Recvprs.
Syntax
%bytesReceived = socket:ReceiveAndParse( [Target=] string, - [[MaxBytes=] number], - [[ParseTokenIndex=] number], - [[Options=] string])
Syntax terms
%BytesReceived | A numeric string to contain the count of the number of bytes received, or to contain 0, if the operation cannot be performed. | ||||||
---|---|---|---|---|---|---|---|
socket | A variable or an expression that is a reference to a Socket object. | ||||||
Target | This name allowed parameter is a %variable or an IMAGE item that is the target of the receive operation. It is referred to as the "receive target." Since you may request that some bytes from the socket stream be discarded, the length of the string stored in this target may be less than the %BytesReceived value. | ||||||
MaxBytes | This optional, name allowed, parameter is the maximum number of bytes of data to receive, less the length of the separator string. This optional argument defaults to 0, which means limit the received data (less separator) to the declared length of the receive target.
If the MaxBytes argument is 0 and the Target argument value is a Longstring, the received data is limited to 2,147,483,647 bytes. The MaxBytes argument value must not exceed 2,147,483,647.
MaxBytes may have the special value | ||||||
ParseTokenIndex | This optional, name allowed, parameter is a %variable or IMAGE item to store the index number (positive integer) of the parse token found in the received data. The ParseTokenIndex value is set to 0 if no token is found within RECVLIM bytes, or if it is not found after more than the number of data bytes specified by the effective value of the MaxBytes argument. | ||||||
Options | This optional, name allowed, parameter is an option string, which can contain either of the following:
|
Usage notes
- ReceiveAndParse return values:
- ReceiveAndParse returns the value -1 if the socket is not open
and
ONRESET CONTINUE
is in effect for the socket. - ReceiveAndParse returns a number greater than 0
which is the number of bytes received from of the socket stream.
"Lengths: maximum, truncation, RECVLIM"
explains the use of the term
number of bytes received
, and it discusses the maxrecvp argument and other values affecting the received string. - ReceiveAndParse returns zero to indicate there is no data remaining to be received on the connection, that is, if FIN has been received or the RECVLIM has been reached.
- ReceiveAndParse returns the value -1 if the socket is not open
and
- In general, you use ReceiveAndParse for a data item whose length is unknown beforehand, but rather is terminated by a known string (or one of a known set of strings). You use the alternate receive operation, Receive, when the protocol in use establishes the length of a data item before it appears in the socket stream.
- The %prsindx argument is used if there is more than one
alternative in the PRSTOK set, and you need to distinguish which alternative
terminated the received value.
For example, with the input stream of
X'36370D38390D'
, the following expression will store the value2
in the variable%prs
.%sk:ReceiveAndParse(%str, , %prs, 'PRSTOK AMBIG|0D0A|0D|0A')
Note that this example uses ambiguous PRSTOK strings (
0D
is a prefix of0D0A
). Considerations for this are discussed in "Ambiguous PRSTOK strings". - The PRSTOK separators are chosen to match the protocol and data streams
that are used with your application.
One of the considerations, of course, is that a separator should not
occur in the "normal" data received by your application.
If that is unavoidable, you will need to use an "escaping"
mechanism; for example, you could use the ASCII
ESC
character (hexadecimal 1B) to indicate that it precedes a character that is to be taken literally. For example, if the data contains non-separator instances ofCR
andESC
:%junk string len 1 %sok:Set('PRSTOK', '0D|1B') Repeat %r = %sok:ReceiveAndParse(%targ, %sep) If %sep eq 2 then %r = %sok:Receive(%junk) %targ = %targ With %junk End If ...
Lengths: maximum, truncation, RECVLIM
The ReceiveAndParse function allows you to locate a separator string, and to store all or part of the string before the separator into the receive target. It is important to understand that when we say "the string that is received in a call to ReceiveAndParse", it may be more than the string that ReceiveAndParse stores in the receive target. This is for the following two reasons:
- The separator string is part of the string received, but it is not stored in the receive target.
- The string before the separator may exceed the size of the target, and thus can be partially discarded (or "truncated").
References to the string received by ReceiveAndParse are to the string stored in the target plus any subsequent bytes that are discarded, plus the separator string.
There are several values that control the length of the string received. They will be discussed in this section, using the following terms:
RECVLIM | This specifies the number of bytes remaining in the "receive window".
A value of zero means there is no limit to the window.
The purpose of this window is to allow you to limit a series of receive
operations (using, if desired, a mixture of Receive and ReceiveAndParse)
to a predetermined total number of bytes.
RECVLIM can be set in a Set call, and subsequent receive operations
decrement from RECVLIM the number of bytes received, until it reaches
zero, at which point a Receive call will return a 0 just as if a A good example of the use of RECVLIM is obtaining a web page, whose length is (usually) specified in theContent-length field of the HTTP response header. |
---|---|
len_to_end | When a receive operation is performed, the received string is
of course limited to the total remaining bytes in the stream that the remote end sent before issuing a close operation. Although this value is not known ahead of time, when describing the operation of receive we use this term to indicate various cases. |
max_recvp | This corresponds to the Maxbytes argument of the ReceiveAndParse function call.
It needs to be specified only if you wish to allow truncation, or if you wish to limit the string stored in the received target to less than the declared the size of the target. You can specify that an unlimited number of bytes can be discarded by specifying -1 as the Maxbytes argument, making the effective value "infinite". The number of bytes received by ReceiveAndParse will not exceed the effective value of this argument plus the length of the separator string. The effective value of max_recvp, if Maxbytes is 0 (its default) or omitted, is targ_size. Truncation can only occur if max_recvp > targ_size, which cannot happen if the target is a Longstring. If a separator string is not found due to a limit imposed by either RECVLIM, len_to_end, or max_recvp, then zero is stored in the parse index target (the ParseTokenIndex argument). |
targ_size | The size of the target is used in calculating various defaults
of the other values here, and it also obviously limits the number of bytes stored in the target and so affects the number of bytes discarded. |
discard_len | This is the number of bytes received, minus the length of the
separator string, minus targ_size. It will always be zero, unless max_recvp is greater than targ_size |
Example
The following example shows part of a program that communicates with a remote
web server and which parses and prints the returned HTML stream.
Note that the second argument to ReceiveAndParse is -1
, which means that there
is no limit to the length of each line parsed, hence no limit to the number
of bytes discarded at the end of the line: only
the first 78 bytes (the size of %s) of each line of HTML is examined
by the User Language program.
%s = %sock:Set('PRSTOK', '0D0A|0A|0D') Repeat %rc = %sock:ReceiveAndParse(%s, -1) Print %s If %rc le 0 then Loop End End If End Repeat %rc = %sock:Close