Example code contained in a recording of a TCP session:
WebTcpipSendBin(hWeb0, "\h0000104F0000005065746572FFFF", 14); // ···O···Peter
The actual business data sent here, the data that should be parameterized, is "Peter" = 0x50 65 74 65 72, but that will not work here. "\h0000104F000000" + sName + "\hFFFF" will not yield the results you might expect. The problem is caused by the zero (0x00) bytes in this string, which Silk Performer (like C) uses for string termination. Therefore all bytes after the first zero byte in a string are ignored when performing such string concatenation.
For manipulation of binary data that may contain zero bytes, you should use the function SetMem. Using the function library detailed below, the above request can be broken into the following lines:
ResetRequestData(); AppendRequestData("\h0000104f000000", 7); AppendRequestData(sName); // e.g., "Peter" AppendRequestData("\hFFFF"); SendTcpipRequest(hSend);
The function library is included using an include file (*.bdh). It uses two global variables for the request data and request data length. The function AppendRequestData appends a string (which may contain zero bytes) to the request buffer, and SendTcpipRequest sends the request data using an open TCP connection.
Here are the contents of the include file, which consists of three functions:
const BUFSIZE := 10000; // maximal size for request data var // global variables for Request data contents and length gsRequestData : string(BUFSIZE); gnRequestLen : number init 0; dclfunc // start a new request string function ResetRequestData begin gnRequestLen := 0; end ResetRequestData; // append data (of length nLen) to the request string // if nLen=0, use strlen(sData) instead function AppendRequestData(sData: string; nLen: number optional): number begin if nLen = 0 then nLen := strlen(sData); end; if nLen + gnRequestLen <= BUFSIZE then // append sData to gsRequestData SetMem(gsRequestData, gnRequestLen + 1, sData, nLen); // the request length has grown by nLen bytes: gnRequestLen := gnRequestLen + nLen; else RepMessage("Request buffer too small!", SEVERITY_ERROR); end; AppendRequestData := gnRequestLen; end AppendRequestData; // Send the request buffer // (TCP-connection identified by hTcp) function SendTcpipRequest (hTcp: number): boolean begin SendTcpipRequest := WebTcpipSendBin(hTcp, gsRequestData, gnRequestLen); end SendTcpipRequest;
When zero bytes are contained in response data, it makes it difficult to search for strings. The reason is that the StrSearch and StrSearchDelimited functions search in a source string only until they hit the first zero byte, which is interpreted as the string terminator.
nPos := BinSearch(sResponseData, nResponseLength, sSearch);
There is no binary counterpart for the StrSearchDelimited function. If you only want to search for strings (as opposed to binary data containing zero bytes), a workaround is to introduce a function that first eliminates all zero bytes from the response data by mapping them (for example, to the byte 0xFF).
Here is a simple version of such a function. Note that it works only if sLeftVal, sRightVal and the string you are searching are strings (meaing, they don't contain zero bytes).
function BinSearchDelimited(sSource : string; nSrcLength: number; sLeftVal : string; sRightVal : string) :string(BUFSIZE) var i : number; begin // eliminate zero bytes in the source string for i:=1 to nSrcLength do if ord(sSource[i]) = 0 then sSource[i] := chr(255); end; end; StrSearchDelimited(BinSearchDelimited, BUFSIZE, sSource, sLeftVal, 1, sRightVal, 1, STR_SEARCH_FIRST); end BinSearchDelimited;