Jump to content

Recommended Posts

Posted (edited)

This is a continuation of this prior discussion. I have been trying to find a reliable way to interact with websockets using AutoIt, which will be a requirement for WebDriver BiDi. Unfortunately, I have yet to find a solution that is acceptable to me --

  • Initially I tried with @FireFox's code, which I modified / shared on  Github.  This worked fine until I realized that calls to _WinHttpWebSocketReceive wouldn't return until something was received. While researching, I found other instances where others ran into the same issue with the WinHttpWebSocketReceive function.
     
  • Next I tried using iola, which is a command-line socket client with REST API. This worked ok, but was complicated by having to read the console output. Also, there wasn't any way to empty the queue of messages AFAICS.
     
  •  My current implementation uses websocat. Again, this works ok, but it lacks the ability to easily detect a failed websocket connection, etc.

Alternatives to consider --


Thanks for reading if you've made it this far. I am requesting input / suggestions on how we can obtain a reliable, working websocket implementation for AutoIt.

Dan

Edited by Danp2
Posted

My websocket UDF:

Only AutoIt code (combine Js from IE core): 😃

 

#RequireAdmin

MsgBox(0x1000, 'Begin', 'Example1')
example1()

MsgBox(0x1000, 'Begin', 'Example2')
example2()

MsgBox(0x1000, 'Begin', 'Example3')
example3()


Func example1()
    Local $oWS = Websocket_Connect('wss://api.bitfinex.com/ws')
    Local $recv = Websocket_Send($oWS)
    
    For $index = 0 To $recv.length - 1
        ConsoleWrite('   - Index ' & $index & ': ' & $recv.index($index) & @CRLF & @CRLF)
    Next

    Websocket_Close($oWS, 1000, '', 20000)
EndFunc


Func example2()
    Local $oWS = Websocket_Connect('wss://api.bitfinex.com/ws')
    Local $recv = Websocket_Send($oWS)
    
    $oJson = $recv.index(0, True)     ;<= True = turn on Json parse
    MsgBox(0x1000, '$oJson.serverId', $oJson.serverId)

    Websocket_Close($oWS, 1000, '', 20000)
EndFunc


Func example3()
    Local $oWS = Websocket_Connect('wss://api.bitfinex.com/ws')
    Local $recv = Websocket_Send($oWS, '{"event":"subscribe","channel":"ticker","pair":"BTCUSD"}')
    
    Local $Timer = TimerInit()
    Do
        Sleep(1000)
        For $index = 0 To $recv.length - 1
            ConsoleWrite('   - Index ' & $index & ': ' & $recv.index($index) & @CRLF & @CRLF)
        Next
        ConsoleWrite('-------------------------------------------------' & @CRLF)
    Until TimerDiff($Timer) > 30000

    Websocket_Close($oWS, 1000, '', 20000)
EndFunc








Func Websocket_Connect($Ws_URL, $protocol = '', $binaryType = False, $timeout = 20000)
    _IE_Emulation(True)
    If @error Then Exit MsgBox(0x40000, 'Fatal Error', 'You must install Internet Explorer 11')
    Local Static $oEvent = ObjEvent('AutoIt.Error', '')
    Local $oWS = ObjCreate("HTMLFILE")
    $Ws_URL = '"' & $Ws_URL & '"'
    If $protocol Then $Ws_URL &= ', [' & StringRegExpReplace(StringRegExpReplace($protocol, '(?i)Sec-WebSocket-Protocol:\s+', '', 1), '(\w+)', '"${1}"') & ']'
    If $binaryType = Default Then $binaryType = False
    
    With $oWS.parentwindow
        .execScript( _
                'Array.prototype.item = function(i,parseJson) {if(typeof parseJson==''undefined''){return this[i]}else{return JSON.parse(this[i])}};' & _ ;Ma thuật giúp autoit thương tác JS Array
                'Array.prototype.index = Array.prototype.item;' & _
                'var recv_data=[], event_close = [], event_error ;' & _
                'let socket = new WebSocket(' & $Ws_URL & ');' & _
                'socket.binaryType = "' & ($binaryType ? 'arraybuffer' : 'blob') & '";' & _
                'socket.onopen = function(event) {};' & _
                'socket.onmessage = function(event) {recv_data.push(event.data)};' & _
                'socket.onclose = function(event) {event_close = event};' & _
                'socket.onerror = function(error) {event_error= error.message};')
        If @error Then Return SetError(1, ConsoleWrite(@CRLF & '! [Websocket_Connect] Your IE don''t support websocket. Please update to IE11' & @CRLF & @CRLF), 0)
        
        Local $ti = TimerInit()
        Do
            Sleep(25)
            If TimerDiff($ti) > $timeout Then Return SetError(2, ConsoleWrite(@CRLF & '! [Websocket_Connect] Connect timeout' & @CRLF & @CRLF))
        Until .eval('socket.readyState') = 1
    EndWith
    
    ConsoleWrite(@CRLF & '> [Websocket_Connect] Connection established' & @CRLF & @CRLF)
    Return $oWS
EndFunc

Func Websocket_Send(ByRef $oWS, $Data = '', $timeout = 60000)
    If $Data Then $oWS.parentwindow.eval('socket').send($Data)
    Local $recv_data = $oWS.parentwindow.eval('recv_data')
    
    Local $ti = TimerInit()
    Do
        Sleep(25)
        If TimerDiff($ti) > $timeout Then Return SetError(1, ConsoleWrite('! [Websocket_Send] Receive timeout' & @CRLF & @CRLF))
    Until $recv_data.length > 0
    
    Return $recv_data
EndFunc

Func Websocket_ResetRecvData(ByRef $oWS)
    $oWS.parentwindow.eval('recv_data.splice(0, recv_data.length);')
EndFunc

Func Websocket_Close(ByRef $oWS, $Code = 1000, $Reason = '', $wait_ms = 0)
    With $oWS.parentwindow.eval('socket')
        .close()
        If .readyState >= 2 Then ConsoleWrite('> [Websocket_Close] The connection is in the process of closing...')
        
        If IsKeyword($wait_ms) Then $wait_ms = 0
        If $wait_ms > 0 Then
            If $wait_ms < 10000 Then $wait_ms = 10000
            Local $ti = TimerInit()
            Do
                Sleep(25)
                If TimerDiff($ti) > $wait_ms Then ExitLoop
            Until .readyState = 3
            If .readyState = 3 Then
                Local $event_close = $oWS.parentwindow.eval('event_close')
                ConsoleWrite('The connection is closed with Code=' & $event_close.code & ($event_close.reason ? ' and Reason=' & $event_close.reason : ''))
            EndIf
        EndIf
        
        $oWS = Null
        ConsoleWrite(@CRLF & @CRLF)
    EndWith
EndFunc




Func _IE_Emulation($vTurnOn = True) ;By Huân Hoàng
    ;https://blogs.msdn.microsoft.com/patricka/2015/01/12/controlling-webbrowser-control-compatibility/
    Local Static $isOn = False
    If $vTurnOn = True And $isOn = True Then Return
    Local Static $_Reg_BROWSER_EMULATION = '\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION'
    Local Static $_Reg_HKCU_BROWSER_EMULATION = 'HKCU\SOFTWARE' & $_Reg_BROWSER_EMULATION
    Local Static $_Reg_HKLM_BROWSER_EMULATION = 'HKLM\SOFTWARE' & $_Reg_BROWSER_EMULATION
    Local Static $_Reg_HKLMx64_BROWSER_EMULATION = 'HKLM\SOFTWARE\WOW6432Node' & $_Reg_BROWSER_EMULATION
    Local $_IE_Mode, $_AutoItExe = StringRegExp(@AutoItExe, '(?i)\\([^\\]+.exe)$', 1)[0]
    Local $_IE_Version = StringRegExp(FileGetVersion(@ProgramFilesDir & "\Internet Explorer\iexplore.exe"), '^\d+', 1)
    If @error Then
        $isOn = False
        Return SetError(1, ConsoleWrite('! [_IE_Emulation]: Cannot get IE Version' & @CRLF & @CRLF), False)
    EndIf
    $_IE_Version = Number($_IE_Version[0])
    Switch $_IE_Version
        Case 10, 11
            $_IE_Mode = $_IE_Version * 1000 + 1
        Case Else
            Return SetError(2, ConsoleWrite('! [_IE_Emulation]: You must install Internet Explorer 10 and Internet Explorer 11' & @CRLF & @CRLF), False)
    EndSwitch
    If $vTurnOn Then
        If RegRead($_Reg_HKCU_BROWSER_EMULATION, $_AutoItExe) <> $_IE_Mode Then RegWrite($_Reg_HKCU_BROWSER_EMULATION, $_AutoItExe, 'REG_DWORD', $_IE_Mode)
        If RegRead($_Reg_HKLM_BROWSER_EMULATION, $_AutoItExe) <> $_IE_Mode Then RegWrite($_Reg_HKLM_BROWSER_EMULATION, $_AutoItExe, 'REG_DWORD', $_IE_Mode)
        If @AutoItX64 And RegRead($_Reg_HKLMx64_BROWSER_EMULATION, $_AutoItExe) <> $_IE_Mode Then RegWrite($_Reg_HKLMx64_BROWSER_EMULATION, $_AutoItExe, 'REG_DWORD', $_IE_Mode)
        $isOn = True
    Else
        RegDelete($_Reg_HKCU_BROWSER_EMULATION, $_AutoItExe)
        RegDelete($_Reg_HKLM_BROWSER_EMULATION, $_AutoItExe)
        If @AutoItX64 Then RegDelete($_Reg_HKLMx64_BROWSER_EMULATION, $_AutoItExe)
        $isOn = False
    EndIf
    Return True
EndFunc

 

 

1.png

Posted (edited)

Hi @NewCommer,

Thanks for reply. I will be sure to check out your code later today. I was just investigating the AHK method, which appears to use a similar technique.

Dan

Edit: Here's a revised example that outputs each received item only once --

Func example4()
    Local $oWS = Websocket_Connect('wss://api.bitfinex.com/ws')
    Local $recv = Websocket_Send($oWS, '{"event":"subscribe","channel":"ticker","pair":"BTCUSD"}')
    Local $Timer = TimerInit(), $sRecv

    With $oWS.parentwindow
        Do
            Sleep(1000)

            If Not $recv.length Then ContinueLoop

            For $index = 0 To $recv.length - 1

                $sRecv = .eval('recv_data.pop();')
                ConsoleWrite('   - Index ' & $index & ': ' & $sRecv & @CRLF & @CRLF)
            Next
            ConsoleWrite('-------------------------------------------------' & @CRLF)
        Until TimerDiff($Timer) > 30000
    EndWith
    Websocket_Close($oWS, 1000, '', 20000)
EndFunc

 

Edited by Danp2
Posted (edited)

It seems that I am unable to connect to an insecure websocket using @NewCommer's  method. The URL provided by webdriver looks like this --

ws://127.0.0.1:9222/session/2f61c225-7604-4cab-ae2d-896e643bc417

Anyone know how to make this work or have other recommended solutions?

Edit: I subsequently confirmed that there isn't an issue with this method and insecure websockets. The above is due to issue with Firefox / Geckodriver when connection is coming from localhost.

Edited by Danp2
Posted
1 minute ago, Danp2 said:

restriction implemented at the browser level

...and that's why I claim that the more we move forward the more we're gonna need SSL and the like. It'd be a can of worms to implement in AutoIt's exe itself but a DLL ( with whatever dependencies it may have ) would be a solution. Then again the DLL would have to do most of it, as AutoIt is quite slow, meaning, that the DLL would have to be quite autonomous and only give results, instead of wanting to chew line by line of transactions via AutoIt's code interaction. That way it would be functional ( for ppl like me ), only selecting/declaring a standardized transaction type of a list of "abilities" within the DLL.
I looked at it once ( some years back ) at the socket level and the handshake itself ( that was some prime number chatter for what I can remember ) lost me at my level of math, so I desisted of the idea of me integrating it in my code. But I followed this thread even before posting because I'd be good for me to have ( given that I can not come up with functional code on my own ).

Anyways, don't mind me. I did not bringing a solution, even tho, I too need one.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

What’s Stopping WebAssembly from Widespread Adoption? 

Will Wasm Have a Proprietary Future?

The future of WebAssembly — beyond the browser at least — seems to reside in the Component Model. But we should also look beyond it to the wider software market.
“There’s going to be venture-backed competition to occupy this space,” Wingo predicted. “Some of this might trickle down to standards but I think a lot of this is going to be proprietary lock-up.”

...I guess external EXE or DLL we can IPC with. But even those in the know can't get a standard going.
 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

I've been working with the WebSocketAsio DLL from above. Seems to work ok in some basic tests, although AutoIt fails to exit properly if any data is sent from the client. Below is the code I've been using to test. Any feedback, suggestions, fixes, etc are appreciated.

Global Const $hWEBSOCKDLL = DllOpen("WebSocketAsio-x86.dll")

Main()

Func Main()
    Local $result

    #cs
    typedef void (*on_connect_t)();
    typedef void (*on_fail_t)(const wchar_t* from);
    typedef void (*on_disconnect_t)();
    typedef void (*on_data_t)(const wchar_t*, size_t);

    EXPORT size_t websocket_register_on_connect_cb(size_t dwAddress);
    EXPORT size_t websocket_register_on_fail_cb(size_t dwAddress);
    EXPORT size_t websocket_register_on_disconnect_cb(size_t dwAddress);
    EXPORT size_t websocket_register_on_data_cb(size_t dwAddress);
    #ce
    Global $hOnConnect = DllCallbackRegister("_WS_OnConnect", "int:cdecl", "")
    Global $hOnDisconnect = DllCallbackRegister("_WS_OnDisconnect", "int:cdecl", "")
    Global $hOnFail = DllCallbackRegister("_WS_OnFail", "int:cdecl", "wstr")
    Global $hOnData = DllCallbackRegister("_WS_OnData", "int:cdecl", "wstr;ulong")

    _WS_EnableVerbose(1)

    _WS_RegisterOnConnectCB($hOnConnect)
    _WS_RegisterOnFailCB($hOnFail)
    _WS_RegisterOnDisconnectCB($hOnDisconnect)
    _WS_RegisterOnDataCB($hOnData)

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_EnableVerbose = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    $result = _WS_IsConnected()
    ;### Debug CONSOLE ↓↓↓
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_IsConnected = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    $sWSURL = "ws://echo.websocket.events:80/"
    $result = _WS_Connect($sWSURL)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_Connect = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    Sleep(2000)

    $result = _WS_Send('{}')
    ;### Debug CONSOLE ↓↓↓
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_Send = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    $result = _WS_Send('{"id":1, "method":"session.status", "params":{}}')
    ;### Debug CONSOLE ↓↓↓
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_Send = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    Sleep(2000)

    $result = _WS_Disconnect()
    ;### Debug CONSOLE ↓↓↓
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_Disconnect = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    ;~ $result = _WS_IsConnected()
    ;### Debug CONSOLE ↓↓↓
    ;~ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _WS_IsConnected = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF)

    Sleep(5000)
    _Shutdown()
EndFunc

Func _Shutdown()
    ConsoleWrite('start shutdown' & @CRLF)
    DllCallbackFree($hOnConnect)
    DllCallbackFree($hOnDisconnect)
    DllCallbackFree($hOnFail)
    DllCallbackFree($hOnData)
    DllClose($hWEBSOCKDLL)
    ConsoleWrite('end shutdown' & @CRLF)
EndFunc

Func _WS_EnableVerbose($iVerbose)
    ; EXPORT void enable_verbose(intptr_t enabled);
    Local $aCall = DllCall($hWEBSOCKDLL, "None:cdecl", "enable_verbose", _
            "INT_PTR", $iVerbose)
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_Connect($sURL)
    ; EXPORT size_t websocket_connect(const wchar_t *szServer);
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_connect", _
            "wstr", $sURL)
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_Send($sData)
; EXPORT size_t websocket_send(const wchar_t *szMessage, size_t dwLen, bool isBinary);
    Local $iLength = StringLen($sData)
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_send", _
            "wstr", $sData, "USHORT", $iLength, "BOOL", 0)
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_Disconnect()
    ; EXPORT size_t websocket_disconnect();
   Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_disconnect")
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_IsConnected()
    ; EXPORT size_t websocket_isconnected();
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_isconnected")
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_RegisterOnConnectCB($hFunc)
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_register_on_connect_cb", _
            "ULONG", DllCallbackGetPtr($hFunc))
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_RegisterOnFailCB($hFunc)
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_register_on_fail_cb", _
            "ULONG", DllCallbackGetPtr($hFunc))
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_RegisterOnDisconnectCB($hFunc)
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_register_on_disconnect_cb", _
            "ULONG", DllCallbackGetPtr($hFunc))
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_RegisterOnDataCB($hFunc)
    Local $aCall = DllCall($hWEBSOCKDLL, "USHORT:cdecl", "websocket_register_on_data_cb", _
            "ULONG", DllCallbackGetPtr($hFunc))
    If @error Then Return SetError(@error, @extended, -1)
    Return $aCall[0]
EndFunc

Func _WS_OnConnect()
    ConsoleWrite('On Connect' & @CRLF)
    return 1
EndFunc

Func _WS_OnFail($sFrom)
    ConsoleWrite('On Fail - ' & $sFrom & @CRLF)
    return 1
EndFunc

Func _WS_OnDisconnect()
    ConsoleWrite('On Disconnect' & @CRLF)
    return 1
EndFunc

Func _WS_OnData($vData, $iLength)
    ConsoleWrite('On Data (' & $iLength  & ') ' & $vData & @CRLF)
    return 1
EndFunc

 

Edited by Danp2
Correct DllCallBackRegister calling method
Posted
On 10/14/2022 at 4:22 PM, Danp2 said:

I believe that the issue I've encountered is more of a security restriction implemented at the browser level

Just a reference:
https://www.stunnel.org/

Cited:

https://www.autoitscript.com/forum/topic/21889-ssl-gmail-with-openssl/?do=findComment&comment=1035990

https://www.autoitscript.com/forum/topic/201896-apache-autoit-https-api-on-autoit/?tab=comments#comment-1460968

 

  • 2 weeks later...
Posted
On 10/11/2022 at 2:17 PM, Danp2 said:

I have yet to find a solution that is acceptable to me

Could you provide a little more information regarding what you would consider acceptable?  What features are required?  I am familiar with the clients you've listed as well as a few others, but I don't want to waste your time by suggesting any clients if they are missing functionality or features that you feel are required.

  • Are you wanting a solution that allows you to maintain Windows 7 compatibility?  Or, is a Window 8+ solution acceptable?
  • You've stated that you would prefer a FOSS solution.  What about a "Free for non-commercial use" solution?
  • Is a DLL-based solution required?  What about another CLI solution?
  • Is full RFC6455 support a requirement or are there some websocket capabilities that are not necessary?
  • The ability to identify disconnected sessions. (Already stated as a requirement or desirable feature)
  • Do you require the ability to automatically restart disconnected sessions?
  • Do you require the ability to send ping/pong "keepalive" messages in order to maintain connections thru aggressive firewalls and NAT.
  • Is your goal to be able to send & receive requests to a websocket server, to be able to subscribe to a websocket server and receive all responses for a given period of time, or both?

In the past, I've written some reliable scripts for both send/receive and subscription-based websocket client use cases.  But like I said, I don't want to waste your time (or mine) by suggesting anything that doesn't meet your minimum requirements.

 :)

Posted

Hi @TheXman,

Thanks for responding. My goal is to find a simple yet reliable way to extend the Webdriver UDF to support the BiDirectional WebDriver Protocol, which is still in development. Here are my responses --

  • Personally, I'm not concerned about maintaining compatibility with older OS versions.
  • Yes, I would consider a  "Free for non-commercial use" solution.
  • The solution doesn't need to be DLL-based. I went that direction after first trying some of the CLI tools because I thought it would allow tighter integration and would eliminate reading console output, etc.
  • TBH, I'm not familiar with the RFC6455 requirements. The Webdriver related communications shouldn't require anything beyond basic websocket functionality AFAIK.
  • Yes, it would be desirable to identify a disconnected session.
  • No, I don't believe that automatic reconnect is a requirement
  • No, ping/pong isn't a requirement
  • Both send/receive requests and subscribe/receive requests are a requirement to fully support the BiDirectional WebDriver Protocol.

Thanks again for your input and prompting me to better define my needs. I look forward to receiving additional input from you on this topic. 😊

Posted
16 minutes ago, Danp2 said:
  • Yes, it would be desirable to identify a disconnected session.
  • No, I don't believe that automatic reconnect is a requirement
  • No, ping/pong isn't a requirement

To know that is disconnected, pong/ping is needed. And if ping/pong is there, automatic reconnect is just an extra line of code ( or 20 :) )

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

Hello @Danp2

In your research, have you come across sgcWebSocketApps?  Although they primarily make components for .Net, Delphi, Lazarus, & C++ Builder, they also have CLI versions that are pretty feature-rich.  I have had success using their WebSocket CLI tools in AutoIT scripts.  As you can see here, they not only support RFC 6455 (the WebSocket Protocol) but they also support other sub protocols and related app API's like: WebRTC, MQTT, SignalR, Kraken, Soket.IO, and STOMP.  Here, you can see that they have been tested using a pretty comprehensive set of test cases and you can also see how they stacked up against Chrome, Firefox, and IE Websocket support.  However, the browsers are a bit dated because the tests were from 2019.

After reading over their documentation, if you think their CLI WebSocket Client and/or their other apps may fit your needs, since I've used them with success in some of my scripts, I may be able to help flatten your learning curve by answering questions you may have or by possibly providing stripped down examples taken from my scripts.

For the record, I have no relationship with or to ESEGECE, I just found their products useful and decided to share them as a possible solution for your future WebDriver WebSocket needs.

🙂

 

Quick Summary of sgcWebSocket CLI Client/Server features:

  • Fully functional multithreaded WebSocket server according to RFC 6455.
  • Supports Windows 32/64.
  • Supports MacOSX 32/64.
  • Supports LINUX.
  • Embedded TCP server for external access to the CLI app.
  • Supports Message Compression using PerMessage_Deflate extension RFC 7692.
  • Supports Text and Binary Messages.
  • WatchDog and HeartBeat built-in support (Keep-Alive & Auto-Reconnect support).
  • Built-in sub-protocols: WebRTC, MQTT (3.1.1 and 5.0) and more. (Built-in refers to the components.  They have standalone CLI tools.)
  • Client Built-in API: SignalR Core, Kraken, STOMP, SocketIO and more. (Built-in refers to the components.  They have standalone CLI tools.)
  • Built-in Javascript libraries to support browser clients. (Built-in refers to the components.  They have standalone CLI tools.)
  • SSL/TLS Support for Server / Client Components.

 

 

 

Edited by TheXman
Posted (edited)

@TheXmanYes, I've looked at this as recently as yesterday. However, I never tried their client tools because I assumed that they weren't applicable for my needs. Clearly I need to take a closer look. Thanks for the recommendation! :thumbsup:

Edit: Looks like I even downloaded the client a few weeks back, extracted the zip file but failed to investigate further. 🙄

Edited by Danp2

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
×
×
  • Create New...