问题描述
我目前正在编写一个 Visual Basic 脚本,该脚本在本地机器 ip (127.0.0.1) 和端口 8181 上打开一个 TcpListener.我从 Google Chrome 连接到我的 websocket 服务器(通过 AcceptSocket 方法).从 Chrome 我向服务器发送请求,服务器可以读取它以及所有内容.当我发回消息(如回声)时,我可以第一次发送,但第二次我收到错误:
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:
收到意外的继续帧.
我需要的是一个 CByte,它告诉框架开始一个新的或结束打开的一个(不关闭套接字连接)
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?
我用 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
更新:
将行 Dim reply(bLength + 1) As Byte
更改为 Dim reply(bLength) As Byte
后,我没有得到连续帧错误,而是得到了一个新的错误:
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:
服务器不能屏蔽它发送给客户端的任何帧.
希望这些信息可以指出问题.
Hopefully this information can point to the problem.
更新 2:
下面是整个客户端 Sub 与客户端一起做所有事情.从接受到握手再到消息.
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
更新 3(解决方案):
Update 3 (solution):
我已经解决了我的问题.通过将 frame(1) = CByte(rawData.Length)
更改为 frame(1) = CByte(rawData.Length + 1)
它合并了结尾 0 字节,现在消息的适当长度是正确的,并且消除了我的掩蔽问题.我猜消息字节的结尾应该包含在消息长度中.
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.
推荐答案
看起来您在消息的末尾包含了一个额外的字节.该不该行
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
改为
Dim reply(bLength) As Byte
相反?您在消息中只需要操作码 + 长度 (frameCount
) + 消息 (rawData.Length
).websocket 客户端会将这些字节读取为完整、有效的消息.然后它将读取您消息中的剩余字节作为新消息的开始,从而有效地破坏您实际发送的下一条消息.
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.
这篇关于Websocket 新帧字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!