0

現在、ローカルマシンのIP(127.0.0.1)とポート8181でTcpListenerを開くVisual Basicスクリプトを作成しています。GoogleChromeから(AcceptSocketメソッドを介して)WebSocketサーバーに接続します。Chromeからサーバーに送信リクエストを実行すると、サーバーはそれとすべてを読み取ることができます。メッセージを(エコーのように)送り返すと、最初はメッセージを送信できますが、2回目はエラーが発生します。

Received unexpected continuation frame.

私が必要としているのは、フレームに新しいものを開始するか、開いているものを終了するように指示するCByteです(ソケット接続を閉じずに)

これは達成可能ですか?もしそうなら、解決策は何ですか?

私はサブを呼び出しますSendMessage(sck, "test")

メッセージ送信者のコードは次のとおりです。

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、連続フレームエラーは発生しませんが、代わりに新しいエラーが発生します。

A server must not mask any frames that it sends to the client.

うまくいけば、この情報が問題を示している可能性があります。

アップデート2:

以下はクライアント全体ですSubはクライアントですべてを行います。承諾から握手、メッセージまで。

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(解決策):

私は自分の問題を理解しました。これに変更frame(1) = CByte(rawData.Length)するframe(1) = CByte(rawData.Length + 1)と、最後の0バイトが組み込まれ、メッセージの適切な長さが正しくなり、マスキングの問題が解消されます。メッセージバイトの終わりがメッセージの長さに含まれることになっていると思います。

4

1 に答える 1

1

メッセージの末尾に余分なバイトが含まれているようです。行すべきではない

Dim reply(bLength + 1) As Byte

に変更されます

Dim reply(bLength) As Byte

代わりは?メッセージに必要なのは、オペコード + 長さ ( frameCount) + メッセージ ( rawData.Length) だけです。Websocket クライアントは、これらのバイトを完全な有効なメッセージとして読み取ります。次に、メッセージから残りのバイトを新しいメッセージの開始として読み取り、実際に送信する次のメッセージを効果的に破損します。

于 2013-01-31T08:58:24.523 に答える