PDA

View Full Version : int -> binary -> string



dazappa
05-12-2010, 01:40 AM
It's tough to explain, but I'm in a rather interesting situation. I've started playing with some HTML5, and wanted to build a simple client/server, with the server being in Pascal. Long story short, a special handshake needs to take place and I'm having trouble writing the code for it.

What I've been searching for, more or less, is a function or set of functions similar to the php function http://php.net/manual/en/function.pack.php

(where I would be using option 'N' like so):


echo pack('N', 259970620);

and the output is "~?ñ<"

I'm just not sure what do do... I can't seem to find any reference to converting an integer to actual binary (or maybe I'd want bytes in this case?) and then to a string. At the moment I've mostly been nabbing random functions from around the net, but they all return the binary as a string ("10010101"), not the (I guess) ansi representation of the binary, and all 3 functions produce a different result for the same integer, and then there's the matter of the last step again.

Rant:
I feel sorry for any others out here who try to play with websockets. The handshake is just utter nonsense that some fool made up for no reason. Look it up on wikipedia, it's hilarious. You're given two key strings. You remove all characters that are not 0-9. You count the number of spaces. You divide the concat'd numbers (after removing non-numbers and spaces) by the number of spaces, now do the same for the second key. Now convert these to some sort of binary string (independently of each other), concat them, then concat that with some 8 byte nonsense also given to you, then md5 it, then send it back.

^ and the initial connection is an HTTP GET, with which after you complete the handshake it pretends it's a normal TCP connection.

User137
05-12-2010, 02:12 AM
I don't really understand what you are after, and i don't know about pack function but this is some tips about binary.

You didn't tell about the problem directly so i may assume you would actually read the bit states from the string? If that's the case i can show alternative how to read bit states of integer very quickly:
Say we have i1 and i2 variables.
i1 is number that we want to know bit state from
i2 tells which bit we want to read

procedure TForm1.FormCreate(Sender: TObject);
var i1,i2: integer;
begin
i1:=192; // In bits this means 1100 0000
i2:=128; // In bits this means 1000 0000
if (i2 and i1)<>0 then
caption:='1'
else
caption:='0';
end;
The program will return '1' because both numbers contain at least 1 bit in same position. If i2 was 4 (0000 0100) it would return '0' because 3rd bit in i1 is 0.

Also you can use operators shl and shr to move bits left or right.

AthenaOfDelphi
05-12-2010, 11:27 AM
Hi dazappa,

I'm not sure whether this is an HTML5 issue or an HTTP protocol issue. Either way, the pack('N' function performs a binary pack of a 32bit integer in big endian order.

If you know you're never going to deal with negative numbers then you can do this:-



result:=chr(data div 16777216)+chr(data div 65536)+chr(data div 256)+chr (data mod 256)


However, a safer alternative is this:-



result:=chr(data and $ff);
data:=data shr 8;
result:=chr(data and $ff)+result;
data:=data shr 8;
result:=chr(data and $ff)+result;
data:=data shr 8;
result:=chr(data and $ff)+result;


This should handle the packing of negative as the negative bit (2's compliment integers) will be shifted down to become just another character.

Using the example you gave, 259970620, this becomes $F7ED63C in hex. $7E = ~, $D6 = the O with umlaut (although exact representation seems to depend on character set), $3c becomes <. The leading $0f is obviously not visible as it's an ASCII control code.

The only other thing I'll say is to reiterate my opening... is this an HTTP protocol issue (in which case I'd use a ready made server such as the one that is supplied with Indy - I use it commercially and it's pretty dam good in terms of stability. When it gets a request you just get an event that provides the request and response objects and from there you can do pretty much anything) or is this an HTML5 issue (if so, I'm suprised they are wanting binary packed data like this... as I understand HTML it's meant to be plain text, certainly I've never had to handle binary data like this, then again, I haven't tinkered with HTML5, but I have tinkered at length with HTTP and previous HTML versions).

Hope this helps.

dazappa
09-12-2010, 04:10 AM
Sorry, I had to run off a bit to get in some study time.

Looks like I was close to you first snippet, but not close enough. Anyway, while it does seem to work as intended, my own code is failing elsewhere. I think I'll just wait for the next version of the protocol...

Anyway, it's not an HTTP protocol issue. WebSockets are a proposed spec for HTML5 to get rid of the typical polling systems used. It initiates a TCP connection and sends GET headers (as a complete HTTP GET request), to which you basically have to pack 2 keys, and concat them with the third key and send it back for "authentication", to which afterward it acts just like TCP. WebSockets isn't a protocol, but TCP with this required handshake on connect.

Send it incomplete information, the connection stalls while waiting. Send it complete, but wrong information and the socket is terminated. (I am at this last stage here, of it not liking what I'm sending back and suiciding)

I'll probably setup my own Pas client to verify the data is correct... with WebSockets you aren't notified about the connection process. On receive events are not triggered in your code until the handshake has been completed.

Murmandamus
09-12-2010, 05:41 AM
When you send binary data over the net, you have to send it in "network byte order", which means that any binary values larger than 8 bits/1 byte have to be ordered a specific way: Big-Endian, or what I call "Intel-hostile".

Rather than writing your own routines for it (which would likely not be portable to other platforms), use the sockets api calls which translate binary data to network byte order:

Use the WinSock unit, and the following functions to do the conversions:

ntohs() - network to host, short
ntohl() - network to host, long
htons() - host to network, short
htonl() - host to network, long

Then, it is just a matter of casting them as char arrays and concating them to your string.