Helpful Information
 
 
Category: Visual Basic Programming
query string decoding?

Does anyone know how to decode a HL server query string?
Here is a query code



Private Sub send_Click()
winsock.RemoteHost = ip 'server ip
winsock.RemotePort = CInt(Port) 'server port
winsock.SendData Char(255) & Char(255) & Char(255) & Char(255) & "players"
End Sub


Private Sub winsock_DataArrival(ByVal bytesTotal As Long)
Dim Data As String
winsock.GetData Data, , bytesTotal 'returned packet
End Sub


It returns some crazy string that needs to be decoded or something?

Don't think anyone can help you unless you tell us what the encoding method from the server is first (or provide us a sample string possibly) :)

the return data is inthe following format

(int32) -1
(byte) ASCII 'D' (players response, S2A_PLAYER)
(byte) active client count
for each active client
(byte) client number / index
(string) player name
(int32) client's frag total
(float32) client's total time in-game

sample data returned , I recieved the data as string:


ÿÿÿÿD
Cygnus )ŒBLee KUM Kee  Êã’Cwildchild )ÿÙBMeMp|-|IS i2AiNeS  ó6_DMr.Deagle
ùYE[needclan] CsMaster  ótäD


Most of the time asc() works to turn the strings into numbers but negative numbers dont work with asc()?

have you tried defining the data variable as a user defined type / structure in the same format as the data?
or as a byte array while you debug...

byte array is okay, but is it correct that say -1 ( negative one)
is 255 as a byte because thats what i get, and so on -2 = 254, -3 = 243 is that right?

i would have thought that a 32 bit int would be spread over 4 bytes - and for -1 you'll get four 255's in each of the bytes ... but you're right that the negatives are 255 = 2^8-1 = -1, 254 = -2 etc. for 8 bit. 65535 = 2^16-1 = -1, 65534 = -2 for 16bit and so on, if you follow

if you read the first value into a long it should just come out as -1
ie (i guess)
Private Sub winsock_DataArrival(ByVal bytesTotal As Long)
Dim Data As String, MinusOne as Long
winsock.GetData MinusOne, , 4
winsock.GetData Data, , bytesTotal-4
End Sub

What do you think?

i think the tidiest way might be to read into user defined structures like this (from the top of my head)
Private Type Header
MinusOne as Long
Response as Byte
PlayerCount as Byte
End Type

Private Type Player
Index as Byte
Name as String
FragTotal as Long
TimeTotal as Double
End Type

Private Sub winsock_DataArrival(ByVal bytesTotal As Long)
Dim Header as Header, Player as Player, i as Byte
call winsock.GetData(Header, , Len(Header))
For i=1 to Header.PlayerCount
call winsock.GetData(Player, , Len(Player))
Next i
End SubDoes that make sense? Like I say, it's off the top of my head so I don't necessarily expect to to work straight off - just to illustrate what i mean

it sounds good :)
I get error " only user-defined types defined in public objects modules can be coerced to or from a variant or passed to late-bound functions" and it points to "Call Winsock.GetData(Header, , Len(Header))" and hilights Header

Try playing around a bit with where you declare the type (at the top of which module) and also try changing Private Type to Public Type etc. and see what the compiler accepts

ya, i tried placing it everywhere and changed to public and stuff, still gives me that error....

I have problem with getting data from a winsock packet....
in the udp it returns int32 along with strings and float32
so the first int32

i go

dim num as long
winsock.getdata num,vblong,4

But i get an error saying that the "datagram is too large to fit into the buffer and is trucated", what does that mean? isnt Long 4 bytes?

Also if I just do the bytes array like

dim bytes() as byte
winsock.getdata bytes

the float32 is spread in 4 slots, like bytes(1), bytes(2), bytes(3), and bytes(4), so how can they be turn it into a single number?

yes, a long is 4 bytes (you can use LenB to check)
I think you can possibly load the float the same way (into a single?) ... otherwise you could experiment with some different numbers and see what you get in your byte array for different float values.

like turn those 4 bytes into one number, I tried

clng(bytes(1)&bytes(2)&bytes(3)&bytes(4))

but it doesnt work, it gives over flow error.

no, i mean find out (search the net, i guess) how vb stores floats and reconstruct the relevant value from the byte array. what happens if you read directly into a single?

some links...

an explanation of converting from single number to underlying bytes
http://www.cis.udel.edu/~sullivan/cs181/lectures/InternalRep.html

a microsoft description:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/decla_36.asp

and a description of the byte representation:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_IEEE_Floating.2d.Point_Representation_and_Microsoft_Languages.asp
(I think there's an error in that the sign bit is missing from the real * 4 definition and the mantissa has nine bits ... i guess that the first mantissa bit should, in fact, be the sign bit

here's a conversion function from the top of my head:
Option Base 0

Public Function bytesToSingle(ByRef bytes() As Byte) As Single
Dim sign As Integer, exponent As Byte, mantissa As Long
Let sign = IIf(bytes(0) \ 128, -1, 1)
Let exponent = (2 * (bytes(0) And 127) + bytes(1) \ 128)
Let mantissa = (bytes(1) Or 128) * 65536& _
+ bytes(2) * 256& _
+ bytes(3)
Let bytesToSingle = sign * mantissa * 2 ^ (exponent - 150)
End Function

WOW, ya I read that and it explains stuff
Your code turns the bytes into single, i suppose it does it correctly, but single is different from long or float32? Because i tested it with the bytes I recieve from the query and it over flows for most of them.....



A float in C++ is typically: composed of 32 bits (4 bytes) comprised of:
1. A sign bit.
2. 8 bit exponent (bias of 127)
3. 23 bit mantissa


for example:
1. 167
2. 85
3. 23
4. 68

turns into 1.763713E-15 (with your function)

and over flows with

1. 152
2. 109
3. 231
4. 67

You need don't need to know which format vb uses - just what is used by your wisock source.

A good way to find out is to see how 0.5, 0.25, 0.125 or similar are represented. I guess the two questions are whether the eponent comes before or after the mantissa and whether the leading 1 bit of the mantissa is implied or included.

If you can see what four-byte arrays you get for the above numbers then you can build from there.

I'e edited the above function, by the way ... I made a mistake with the sign bit.


... one more thing ... the overflow error is from the bytes(2) * 256 line in function. The temporary calculation is being done on the integer range - which the result is too big for. So change to bytes(2) * 256& to force long integer calculation.

Or just use microsoft's solution, or at least thats what they say, http://support.microsoft.com/default.aspx?scid=KB;en-us;q171652

hmmmm......?

if the information going into the byte array is in the format you need, there's no need to use the byte array at all - just read into a user defined type or a single.

well thats the problems, it gives an error when I try the Type it gives error: "only user-defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions". I define the type in module and in the form...
then when I try reading into long, or even into a string just part of a packet like 5 bytes of it, it give an error: "datagram is too large to fit into the buffer and is trucated"










privacy (GDPR)