Reputation: 1794
I am currently writing a Visual Basic script that opens a TcpListener on local machine ip (127.0.0.1) and on port 8181. I connect to my websocket server (via the AcceptSocket method) from Google Chrome. From Chrome i do a send request to the server and the server can read it and everything. When I send the message back (like an echo) I can send it the first time but the second time I get an error:
Received unexpected continuation frame.
What i need is a CByte that tells the frame to start a new one or end the open one (without closing the socket connection)
Is this achieveable and if so what is the solution?
I call the Sub with SendMessage(sck, "test")
Here is the code for my message sender:
Sub SendMessage(sck As Socket, message As String)
Dim rawData = System.Text.Encoding.UTF8.GetBytes(message)
Dim frameCount = 0
Dim frame(10) As Byte
frame(0) = CByte(129)
If rawData.Length <= 125 Then
frame(1) = CByte(rawData.Length)
frameCount = 2
ElseIf rawData.Length >= 126 AndAlso rawData.Length <= 65535 Then
frame(1) = CByte(126)
Dim len = CByte(rawData.Length)
frame(2) = CByte(((len >> 8) & CByte(255)))
frame(3) = CByte((len & CByte(255)))
frameCount = 4
Else
frame(1) = CByte(127)
Dim len = CByte(rawData.Length)
frame(2) = CByte(((len >> 56) & CByte(255)))
frame(3) = CByte(((len >> 48) & CByte(255)))
frame(4) = CByte(((len >> 40) & CByte(255)))
frame(5) = CByte(((len >> 32) & CByte(255)))
frame(6) = CByte(((len >> 24) & CByte(255)))
frame(7) = CByte(((len >> 16) & CByte(255)))
frame(8) = CByte(((len >> 8) & CByte(255)))
frame(9) = CByte((len & CByte(255)))
frameCount = 10
End If
Dim bLength = frameCount + rawData.Length
Console.WriteLine(frameCount)
Console.WriteLine(rawData.Length)
Dim reply(bLength + 1) As Byte
Dim bLim = 0
For i = 0 To frameCount - 1
Console.WriteLine(bLim)
reply(bLim) = frame(i)
bLim += 1
Next
For i = 0 To rawData.Length - 1
Console.WriteLine(bLim)
reply(bLim) = rawData(i)
bLim += 1
Next
For i = 0 To reply.Length - 1
Console.WriteLine("Byte: " & reply(i))
Console.WriteLine("Char: " & CByte(reply(i)))
Next
sck.Send(reply, reply.Length, 0)
End Sub
Update:
After changing the line Dim reply(bLength + 1) As Byte
to Dim reply(bLength) As Byte
i dont get the continuous frame error, but instead i get a new error:
A server must not mask any frames that it sends to the client.
Hopefully this information can point to the problem.
Update 2:
Below is the entire client Sub the does everything with the clients. From accept to handshake to message stuff.
Private Sub clientStarter(ByVal sck As Socket)
Dim netStream As New NetworkStream(sck)
Dim netReader As New IO.StreamReader(netStream)
Dim netWriter As New IO.StreamWriter(netStream)
Dim key As String = ""
Console.WriteLine("Accept new connection ...")
'' Reading handshake message
While (True)
Dim line As String = netReader.ReadLine()
If line.Length = 0 Then
Exit While
End If
If (line.StartsWith("Sec-WebSocket-Key: ")) Then
key = line.Split(":")(1).Trim()
End If
Console.WriteLine("Data: " & line)
End While
'' Calculate accept-key
key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
key = getSHA1Hash(key)
'' Response handshake message
Dim response As String
response = "HTTP/1.1 101 Switching Protocols" & vbCrLf
response &= "Upgrade: websocket" & vbCrLf
response &= "Connection: Upgrade" & vbCrLf
response &= "Sec-WebSocket-Accept: " & key & vbCrLf & vbCrLf
netWriter.Write(response)
netWriter.Flush()
Dim dataSent As [Byte]() = Nothing
Dim dataRecieved(1024) As [Byte]
Dim bytes As Int32
Console.WriteLine(dataRecieved)
Dim message As String = Nothing
While (True)
If (sck.Connected = False) Then
Exit While
End If
bytes = sck.Receive(dataRecieved, dataRecieved.Length, 0)
'Console.WriteLine(bytes)
While (bytes > 0)
Console.WriteLine("recieved Data")
message = System.Text.Encoding.UTF8.GetString(dataRecieved, 0, bytes)
Console.WriteLine(bytes)
bytes = 0
If (bytes = 0) Then
Console.WriteLine("test")
Console.WriteLine(message)
dataSent = System.Text.Encoding.UTF8.GetBytes(message, 0, bytes)
SendMessage(sck, "test")
message = Nothing
End If
End While
End While
End Sub
Update 3 (solution):
I have figured out my problem. By changing frame(1) = CByte(rawData.Length)
to frame(1) = CByte(rawData.Length + 1)
it incorperates the end 0 byte and now the proper length of the message is correct and rids me of my masking problem. I guess the end of the message byte is supposed to be included in the message length.
Upvotes: 0
Views: 1637
Reputation: 42165
It looks like you're including an extra byte at the end of your message. Shouldn't the line
Dim reply(bLength + 1) As Byte
be changed to
Dim reply(bLength) As Byte
instead? All you need in your message is opcode + length (frameCount
) + message (rawData.Length
). A websocket client will read these bytes as a full, valid message. It will then read the remaining byte from your message as the start of a new message, effectively corrupting the next message you actually send.
Upvotes: 1