WebSockets work slightly differently to sockets on other platforms. Normally you'd connect with ConnectSocket() and then be able to send and receive data without doing anything else. However when an HTML5 app calls ConnectSocket() it starts with the normal TCP connection process, so the app on the other end will see a valid socket connection, but then the HTML5 app will send some data (roughly 500 bytes of it) without you doing anything. This is the request header from
this page, the device at the other end of the connection must send back the response text before HTML5 app will complete the socket connection.
I decided to try it out for myself, here's what I came up with.
Server, run on a non-HTML5 platform
// set window properties
SetWindowTitle( "WebSocket Receiver" )
SetWindowSize( 1024, 768, 0 )
// set display properties
SetVirtualResolution(1024,768)
SetScissor(0,0,0,0)
socket = 0
handshake = 0
CreateSocketListener( 1, "", 6547 )
do
// will only receive 1 connection, but listener will remain active if you want to accept more
if ( socket = 0 )
socket = GetSocketListnerConnection(1)
endif
if ( socket > 0 and handshake = 0 )
// receive the web socket request header
received$ = ""
newlines = 0
repeat
// wait for data, might want to break out of this loop if some time has passed
while( GetSocketBytesAvailable(socket) = 0 )
endwhile
byte = GetSocketByte(socket)
received$ = received$ + chr(byte)
// handshake request will be terminated by a double new line \r\n\r\n
if ( byte <> 10 and byte <> 13 ) // new line or carriage return
newlines = 0
else
if ( byte = 10 ) then newlines = newlines + 1 // only count new line character
endif
until newlines = 2
// find websocket key and construct the correct response
pos = FindString( received$, "Sec-WebSocket-Key: " )
if ( pos > 0 )
pos = pos + len( "Sec-WebSocket-Key: " )
key$ = mid( received$, pos, -1 )
pos = FindString( key$, chr(13) )
if ( pos > 0 ) then key$ = left( key$, pos-1 )
// modify key
key$ = key$ + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
hash$ = sha1(key$)
hash$ = HexToBase64(hash$)
// construct response
response$ = "HTTP/1.1 101 Switching Protocols" + chr(13) + chr(10)
response$ = response$ + "Upgrade: websocket" + chr(13) + chr(10)
response$ = response$ + "Connection: Upgrade" + chr(13) + chr(10)
response$ = response$ + "Sec-WebSocket-Accept: " + hash$ + chr(13) + chr(10)
response$ = response$ + chr(13) + chr(10)
// send response
for i = 1 to len(response$)
byte = asc(mid(response$,i,1))
SendSocketByte(socket,byte)
next i
FlushSocket(socket)
handshake = 1
endif
endif
Print(ScreenFPS())
print("Socket ID: " + str(socket))
print("Handshake done: " + str(handshake))
sync()
loop
function HexToBase64( input as string )
b64values as string[]
b64values = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
"Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
"g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"]
b64string as string = ""
length = len(input) / 2 // hex has two characters per byte
extra = mod(length,3)
if ( length = 0 ) then exitfunction ""
pos = 1
for i = 1 to length/3
// first byte
temp$ = mid(input, pos, 2)
value1 = Val(temp$,16)
pos = pos + 2
// second byte
temp$ = mid(input, pos, 2)
value2 = Val(temp$,16)
pos = pos + 2
// third byte
temp$ = mid(input, pos, 2)
value3 = Val(temp$,16)
pos = pos + 2
b64value1 = value1 >> 2
b64value2 = ((value1 && 3) << 4) || (value2 >> 4)
b64value3 = ((value2 && 15) << 2) || (value3 >> 6)
b64value4 = value3 && 63
b64string = b64string + b64values[b64value1] + b64values[b64value2]
b64string = b64string + b64values[b64value3] + b64values[b64value4]
next
if ( extra > 0 )
temp$ = mid(input, pos, 2)
value1 = Val(temp$,16)
pos = pos + 2
value2 = 0
if ( extra > 1 )
temp$ = mid(input, pos, 2)
value2 = Val(temp$,16)
pos = pos + 2
endif
b64value1 = value1 >> 2
b64value2 = ((value1 && 3) << 4) || (value2 >> 4)
b64value3 = ((value2 && 15) << 2)
b64string = b64string + b64values[b64value1] + b64values[b64value2]
if ( extra = 2 )
b64string = b64string + b64values[b64value3] + "="
else
b64string = b64string + "=="
endif
endif
endfunction b64string
Client, run on HTML5
SetVirtualResolution(1024,768)
SetScissor(0,0,0,0)
ConnectSocket( 1,"192.168.0.105", 6547, 3000 ) // IP of the server running the above code
while( GetSocketConnected(1) = 0 )
print("Connecting")
Sync()
endwhile
connected = GetSocketConnected(1)
do
Print(ScreenFPS())
print("Connected: " + str(connected))
sync()
loop
After that I tried sending raw data as you would a normal socket but it didn't like it, it just disconnected. I heard something about WebSocket message frames, so maybe it has another special format for those, but I didn't investigate further.