Jump to content

TCPRecv ($ConnectedSocket,4*1024)receive reply data garbled


Go to solution Solved by Danp2,

Recommended Posts

Hey, everybody!  Sorry, my English is terrible!I am using TCPListen to establish a ws service, with the web client to test, the two can be normal connection handshake success, but the client to transmit the data, the server to TCPRecv unknown characters and garbled code?  Can someone help me, please?  Thank you, everybody!
---- The above is from translate

client

GET / HTTP/1.1
Host: 127.0.0.1:3001
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36
Upgrade: websocket
Origin: http://www.emqx.io
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Sec-WebSocket-Key: nveB3rP7f2g6tH4YM9gwmA==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

 

server

HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Location: ws://127.0.0.1:3001
Sec-WebSocket-Accept: KyMUi4zyZa9ENlgXVEH01y5H62c=

 

$rmsg = TCPRecv ($ConnectedSocket,4*1024)

ConsoleWrite("ConsoleWrite:"&$rmsg)

ConsoleWrite:亞5蠨?醬??

I found this on the forum, but it's still the same:
 

Func WebSocketReceive($bytes)
    Return unmask(BinaryToString($bytes))
EndFunc

Func unmask($text)
    Local $length = StringToBinary(StringMid($text, 2, 1))
    $length = BitAND(Number($length), 127)
    Local $masks, $data
    If $length = 126 Then
        $masks = StringMid($text, 5, 4)
        $data = StringMid($text, 9)
    ElseIf $length = 127 Then
        $masks = StringMid($text, 11, 4)
        $data = StringMid($text, 15)
    Else
        $masks = StringMid($text, 3, 4)
        $data = StringMid($text, 7)
    EndIf
    Local $result = ""
    For $i = 0 To StringLen($data) - 1
        $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i,  4) + 1, 1))))
    Next
    Return $result
EndFunc

 

Link to comment
Share on other sites

3 hours ago, AndSoW said:

ConsoleWrite("ConsoleWrite:"&$rmsg)

What do you get if you change this to the following?

ConsoleWrite("BinaryToString:" & BinaryToString($rmsg))

You may want to post a short reproducer script that we can run to observe the issue. For the proper way to post code, follow the instructions at the link.

P.S. You may want to review this thread for some prior discussions on using a websocket client to handle the communications.

Edited by Danp2
added PS
Link to comment
Share on other sites

6 minutes ago, Danp2 said:

What do you get if you change this to the following?

ConsoleWrite("BinaryToString:" & BinaryToString($rmsg))

You may want to post a short reproducer script that we can run to observe the issue. For the proper way to post code, follow the instructions at the link.

P.S. You may want to review this thread for some prior discussions on using a websocket client to handle the communications.

 

After I tested the script with BinaryToString, the data sent back by the client was still a string of garbled code.

I am here to see other authors code to test and learn:BY:milos83

Link to comment
Share on other sites

11 minutes ago, Danp2 said:

What do you get if you change this to the following?

ConsoleWrite("BinaryToString:" & BinaryToString($rmsg))

You may want to post a short reproducer script that we can run to observe the issue. For the proper way to post code, follow the instructions at the link.

P.S. You may want to review this thread for some prior discussions on using a websocket client to handle the communications.

Raw data:111111

BinaryToString:亰铫LK迵}z?

BinaryToString:亞猒$煕n

Link to comment
Share on other sites

Posted (edited)
19 minutes ago, Danp2 said:

Back to this. We can only continue to guess at the problem without seeing your code.

#include <Array.au3>
#include <Crypt.au3>

TCPStartup()
Global $gSocket = TCPListen("127.0.0.1", 3001)
While True
    Local $client = TCPAccept($gSocket)
    If $client <> -1 Then
        Local $data = TCPRecv($client, 1024)
        If StringInStr($data, "Sec-WebSocket-Key:") Then
            ; Perform WebSocket handshake
            Local $key = StringRegExp($data, "Sec-WebSocket-Key: (.+)", 1)[0]
            ConsoleWrite($data & @CRLF)
            ConsoleWrite("$key:" & $key & @CRLF)
            Local $responseKey = base64(_Crypt_HashData($key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", $CALG_SHA1))
            Local $response = "HTTP/1.1 101 Switching Protocols" & @CRLF & _
                             "Upgrade: websocket" & @CRLF & _
                             "Connection: Upgrade" & @CRLF & _
                             "Sec-WebSocket-Accept: " & $responseKey & @CRLF & @CRLF
            TCPSend($client, $response)

            ;Sleep(1000)
            ;WebSocketSend($client, "Hello!"); This works
            ;Sleep(1000)

            ; Now the connection is upgraded to WebSocket, handle communication
            While True
                Local $message = WebSocketReceive($client)
                If @error Then ContinueLoop
                If $message <> "" Then
                    ; Handle the received message
                    ConsoleWrite("Received message: " & $message & @CRLF)
                    ;The received data here is an unknown character
                EndIf
            WEnd
        else
        ConsoleWrite("Received message: " & $data & @CRLF)
        ;The received data here is an unknown character
        EndIf
    EndIf
WEnd

Func WebSocketReceive($socket)
    Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed
    If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data
    Return unmask(BinaryToString($bytes))
EndFunc

Func WebSocketSend($socket, $message)
    Local $length = StringLen($message)
    Local $header = Chr(BitOR(0x80, 0x01)) ; FIN, Opcode Text
    If $length <= 125 Then
        $header &= Chr($length)
    ElseIf $length <= 65535 Then
        $header &= Chr(126) & Chr(BitShift($length, 8)) & Chr(BitAND($length, 0xFF))
    Else
        $header &= Chr(127)
        For $i = 7 To 0 Step -1
            $header &= Chr(BitShift($length, 8 * $i))
        Next
    EndIf
    TCPSend($socket, $header & $message)
EndFunc

Func base64($vCode, $bEncode = True, $bUrl = False)
    Local $oDM = ObjCreate("Microsoft.XMLDOM")
    If Not IsObj($oDM) Then Return SetError(1, 0, 1)
    Local $oEL = $oDM.createElement("Tmp")
    $oEL.DataType = "bin.base64"
    If $bEncode then
        $oEL.NodeTypedValue = Binary($vCode)
        If Not $bUrl Then Return $oEL.Text
        Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "")
    Else
        If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/")
        $oEL.Text = $vCode
        Return $oEL.NodeTypedValue
    EndIf
EndFunc ;==>base64

Func unmask($text)
    Local $length = StringToBinary(StringMid($text, 2, 1))
    $length = BitAND(Number($length), 127)
    Local $masks, $data
    If $length = 126 Then
        $masks = StringMid($text, 5, 4)
        $data = StringMid($text, 9)
    ElseIf $length = 127 Then
        $masks = StringMid($text, 11, 4)
        $data = StringMid($text, 15)
    Else
        $masks = StringMid($text, 3, 4)
        $data = StringMid($text, 7)
    EndIf
    Local $result = ""
    For $i = 0 To StringLen($data) - 1
        $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i,  4) + 1, 1))))
    Next
    Return $result
EndFunc

test url :http://mqtt.uzyiot.com/

and https://www.lddgo.net/en/network/websocket

Edited by AndSoW
Link to comment
Share on other sites

2 minutes ago, Danp2 said:

I'm confused about your ultimate goal. Are you wanting to establish a connection to an existing Websocket server or are you trying to create a websocket server in AutoIt?

trying to create a websocket server in AutoIt! TKS!

Link to comment
Share on other sites

5 minutes ago, Danp2 said:

FWIW, your code works for me if I use a websocket client (in my case, I used Websocket Weasel) to connect to the URL ws://127.0.0.1:3001.

Can we see how you operate?

I don't really understand:(in my case, I used Websocket Weasel)

I tested ws with online html5 and what I received couldn't be parsed.

I'm also looking for reasons and more ways to test results

Link to comment
Share on other sites

13 minutes ago, Danp2 said:

I think that your HTML client is the issue. Websocket Weasel is a Firefox extension that lets you run a WS client directly in your browser. I should be the same thing as accessing https://mhgolkar.github.io/Weasel/. I also successfully tested with the client at https://websocketking.com/.

TKS!

 After the test can indeed receive correctly:https://mhgolkar.github.io/Weasel/

It is possible that our browser language is causing the problem, it is possible that uft-8 is not getting gbk

Link to comment
Share on other sites

12 minutes ago, Danp2 said:

My guess would be that it has something to do with the MQTT-compatible client behaving differently than a standard WS client.

My goal is to learn how to use AutoIt to build MQTT server after learning WS. Many projects are built on other people's platforms, and I try to build my own platform to control my own iot devices. Thank you very much for your patient reply. Please post the question for a few days first. After my testing here, not every time I successfully received the correct data, I will look for other answers. Or there's a better way! TKS!

Link to comment
Share on other sites

  • Solution
On 1/2/2024 at 7:40 AM, AndSoW said:

You may want to review this thread for some prior discussions on using a websocket client to handle the communications.

Did you check out the thread I linked above? This would be the direction I would recommend, especially since AutoIt is single threaded and likely isn't capable of dealing with the complex communications required for WS / MQTT.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...